(* → *) → ((*, *) → *) → ((*, *) → *)(unnamed)The 1-input preprocessing function
(unnamed)The 2-input function to add preprocessor to
A 2-input function that preprocesses its inputs
Given a 1-input preprocessing function p and a 2-input function f, returns a new function that will apply the
preprocessing function to each input before executing f, i.e. (arg1, arg2) => f(p(arg1), p(arg2)).
Useful for cleaning up inputs to a function.
'use strict'
const isString = require('@eluvio/elv-js-helpers/Boolean/isString')
const addPreprocessFn2 = require('@eluvio/elv-js-helpers/Functional/addPreprocessFn2')
const strOrNumToNum = x => isString(x) ? Number(x) : x
const add = (x, y) => x + y
const lenientAdd = addPreprocessFn2(strOrNumToNum, add)
lenientAdd(42, 1) //=> 43
lenientAdd('42', 1) //=> 43
lenientAdd(42, '1') //=> 43
lenientAdd('42', '1') //=> 43
// function is curried: call with 1 argument to obtain a function that will add the given preprocessor to other functions
const allowStringNumInputs = addPreprocessFn2(strOrNumToNum)
const mult = (x, y) => x * y
const lenientMult = allowStringNumInputs(mult)
lenientMult(42, '42') //=> 1764
// call with 3 arguments to obtain a 1-input function that will preprocess its input
const lenientMult42 = addPreprocessFn2(strOrNumToNum, mult, '42')
lenientMult42('42') //=> 1764
// call with 4 arguments to obtain final value instead of a function
const x = 42
const y = '42'
addPreprocessFn2(strOrNumToNum, add, x, y) //=> 84Date → Number → DatesecondsThe number of seconds to add
datetimeJavascript Date object to add to
Adds a specified number of seconds to a Javascript Date object and returns a new Date
'use strict'
const addSeconds = require('@eluvio/elv-js-helpers/Datetime/addSeconds')
const d = new Date('2022-01-01T07:30:00Z')
// Note that following depends on environment's locale settings (shown values are for locale 'en-US')
addSeconds(3600, d).toUTCString() //=> 'Sat, 01 Jan 2022 08:30:00 GMT'
addSeconds(-3600, d).toUTCString() //=> 'Sat, 01 Jan 2022 06:30:00 GMT'(a → Boolean | Pred a) → (a → Boolean | Pred a) → a → Boolean(unnamed)First function that returns a Boolean
(unnamed)Second function that returns a Boolean
Function which takes input, passes to both input functions, and then combines return values with logical AND
Passthrough for the and() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Given two predicate functions (a -> Boolean), returns a function that combines the two using logical AND.
'use strict'
const and = require('@eluvio/elv-js-helpers/Functional/and')
const isEven = x => (x % 2) === 0
const isNegative = x => x < 0
const isNegEven = and(isEven, isNegative)
isNegEven(3) //=> false
isNegEven(2) //=> false
isNegEven(-2) //=> true* → *(unnamed)Any input
The input
Passthrough for Any model from ObjectModel
(Copyright © 2015 Sylvain Pollet-Villard, MIT license)
Used to define fields that can hold any type.
((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → (a → Boolean) → String → [(* → Boolean), ObjectModelErrMsgFn | String]preCheckFnThe preliminary check that must pass in order for assertFn to be checked.
assertFnThe assertion to check.
msgStrOrFnAn error message string or message generating function to use if assertFn returns false.
2-element array [Function, Function]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if assertFn returns true for the input OR preCheckFn returns falsefalse if assertFn returns false for the input AND preCheckFn returns trueThis means that assertFn will only be called if the input first passes preCheckFn, otherwise true
will always be returned (the input is ignored if it fails preCheckFn). The purpose of this is to
allow prevention redundant errors, e.g. both 'expecting Number, got String "foo"' and 'Value must be an integer (got: "foo")'
(by passing in a preCheckFn that returns true if input is a number - if input is not a number, then integer check is skipped)
The second element returned is a function to generate an error message. This function gets called by ObjectModel when
it validates a Model and fails, passing in the assertion result (generally false), the failing value, and any
attribute name(s) that were traversed to access the value.
'use strict'
const passesModelCheck = require('@eluvio/elv-js-helpers/Boolean/passesModelCheck')
const NumberModel = require('@eluvio/elv-js-helpers/Model/NumberModel')
const assertAfterCheck = require('@eluvio/elv-js-helpers/ModelAssertion/assertAfterCheck')
const IntegerModel = NumberModel
.extend()
.assert(
...assertAfterCheck(
passesModelCheck(NumberModel),
n => Number.isInteger(n),
'must be an integer'
)
)
.as('Integer')
IntegerModel(42) //=> 42
IntegerModel(4.2) //=> EXCEPTION: 'Value must be an integer (got: 4.2)'
IntegerModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'
// Compare vs. case where assertAfterCheck is not used:
const assertionErrMsg = require('@eluvio/elv-js-helpers/ModelAssertion/assertionErrMsg')
const IntegerModelNoPrecheck = NumberModel
.extend()
.assert(
n => Number.isInteger(n),
assertionErrMsg('must be an integer')
)
.as('Integer')
IntegerModelNoPrecheck('foo') //=> EXCEPTION: 'expecting Number, got String "foo"\nValue must be an integer (got: "foo")'((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → a → a → Boolean → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]modelThe Model to be bounded
lowerBoundThe lower bound that must be satisfied. If null, no lower bound will be checked.
upperBoundThe upper bound that must be satisfied. If null, no upper bound will be checked.
lowerInclusiveIf true (and lowerBound is not null) then input is allowed to equal lowerBound.
upperInclusiveIf true (and upperBound is not null) then input is allowed to equal upperBound.
comparatorFnFunction used to compare the input against bound(s). Must accept two values and return -1 if first value is less than the second, 1 if the second value is less than the first, and zero otherwise. This enables adding bounds to a Model type that cannot be compared using Javascript's less than (<) operator.
2-element array [Function, Function | String]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if the input satisfies the specified bound(s) OR the input is not a valid instance of the specified Model to be boundedfalse if the input is a valid instance of the specified Model AND violates the specified bound(s)This means that the assertion will PASS if the input is not a valid instance of the Model to be bounded. The purpose of this is to prevent redundant errors, e.g. 'foo' is not a Number, 'foo' must be < 1.
The second element is either an error string or a function to generate an error message. If it is a function, it will
get called by ObjectModel when it validates a Model and fails, passing in the assertion result (generally false),
the failing value, and any attribute name(s) that were traversed to access the value.
'use strict'
const NumberModel = require('@eluvio/elv-js-helpers/Model/NumberModel')
const assertBounded = require('@eluvio/elv-js-helpers/ModelAssertion/assertBounded')
// Note use of spread operator (...) to unpack the array returned by assertBounded()
const NumberBetweenZeroAndOneModel = NumberModel.extend()
.assert(...assertBounded(NumberModel, 0, 1, true, true))
.as('NumberBetweenZeroAndOne')
NumberBetweenZeroAndOneModel(-1) //=> EXCEPTION: 'Value must be >= 0 and <= 1 (got: -1)'
NumberBetweenZeroAndOneModel(0) //=> 0
NumberBetweenZeroAndOneModel(0.5) //=> 0.5
NumberBetweenZeroAndOneModel(1) //=> 1
NumberBetweenZeroAndOneModel(42) //=> EXCEPTION: 'Value must be >= 0 and <= 1 (got: 42)'((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → a → a → Boolean → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]modelThe Model to be bounded
lowerBoundThe lower bound that must be satisfied.
upperBoundThe upper bound that must be satisfied.
lowerInclusiveIf true then input is allowed to equal lowerBound.
upperInclusiveIf true then input is allowed to equal upperBound.
comparatorFnFunction used to compare input against lowerBound and upperBound.
Must accept two values and return -1 if first value is less than the second,
1 if the second value is less than the first, and zero otherwise.
This enables adding bounds to a Model type that cannot be compared using Javascript's
less than (<) operator.
2-element array [Function, Function]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if the input satisfies the specified bounds OR the input is not a valid instance of the specified Model to be boundedfalse if the input is a valid instance of the specified Model AND violates the specified bounds.This means that the assertion will PASS if the input is not a valid instance of the Model to be bounded. The purpose of this is to prevent redundant errors, e.g. 'foo' is not a Number, 'foo' must be > 0 and < 42.
The second element is a function to be called by ObjectModel to construct an error message if the bounds validation fails.
'use strict'
const compare = require('@eluvio/elv-js-helpers/Functional/compare')
const IntegerModel = require('@eluvio/elv-js-helpers/Model/IntegerModel')
const assertBoundedBetween = require('@eluvio/elv-js-helpers/ModelAssertion/assertBoundedBetween')
// Note use of spread operator (...) to unpack the array returned by assertBoundedBetween()
const CartonEggCountModel = IntegerModel
.extend()
.assert(
...assertBoundedBetween(
IntegerModel,
0,
12,
true,
true,
compare
)
)
.as('CartonEggCount')
CartonEggCountModel(0) //=> 0
CartonEggCountModel(6) //=> 6
CartonEggCountModel(12) //=> 12
CartonEggCountModel(42) //=> EXCEPTION: 'Value must be >= 0 and <= 12 (got: 42)'
CartonEggCountModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → a → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]modelThe Model to be bounded
lowerBoundThe lower bound that must be satisfied.
inclusiveIf true (and lowerBound is not null) then input is allowed to equal lowerBound.
comparatorFnFunction used to compare input against lowerBound.
Must accept two values and return -1 if first value is less than the second,
1 if the second value is less than the first, and zero otherwise.
This enables adding bounds to a Model type that cannot be compared using Javascript's
less than (<) operator.
2-element array [Function, Function]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if the input satisfies the specified bound OR the input is not a valid instance of the specified Model to be boundedfalse if the input is a valid instance of the specified Model AND violates the specified bound.This means that the assertion will PASS if the input is not a valid instance of the Model to be bounded. The purpose of this is to prevent redundant errors, e.g. 'foo' is not a Number, 'foo' must be > 1.
The second element is a function to be called by ObjectModel to construct an error message if the bounds validation fails.
'use strict'
const compare = require('@eluvio/elv-js-helpers/Functional/compare')
const IntegerModel = require('@eluvio/elv-js-helpers/Model/IntegerModel')
const assertBoundedLower = require('@eluvio/elv-js-helpers/ModelAssertion/assertBoundedLower')
// Note use of spread operator (...) to unpack the array returned by assertBoundedLower()
const PositiveIntegerModel = IntegerModel
.extend()
.assert(
...assertBoundedLower(
IntegerModel,
0,
false,
compare
)
)
.as('PositiveInteger')
PositiveIntegerModel(1) //=> 1
PositiveIntegerModel(0) //=> EXCEPTION: 'Value must be > 0 (got: 0)'
PositiveIntegerModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → a → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]modelThe Model to be bounded
upperBoundThe upper bound that must be satisfied.
inclusiveIf true (and upperBound is not null) then input is allowed to equal upperBound.
comparatorFnFunction used to compare input against upperBound.
Must accept two values and return -1 if first value is less than the second,
1 if the second value is less than the first, and zero otherwise.
This enables adding bounds to a Model type that cannot be compared using Javascript's
less than (<) operator.
2-element array [Function, Function]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if the input satisfies the specified bound OR the input is not a valid instance of the specified Model to be boundedfalse if the input is a valid instance of the specified Model AND violates the specified bound.This means that the assertion will PASS if the input is not a valid instance of the Model to be bounded. The purpose of this is to prevent redundant errors, e.g. 'foo' is not a Number, 'foo' must be < 42.
The second element is a function to be called by ObjectModel to construct an error message if the bounds validation fails.
'use strict'
const compare = require('@eluvio/elv-js-helpers/Functional/compare')
const IntegerModel = require('@eluvio/elv-js-helpers/Model/IntegerModel')
const assertBoundedUpper = require('@eluvio/elv-js-helpers/ModelAssertion/assertBoundedUpper')
// Note use of spread operator (...) to unpack the array returned by assertBoundedUpper()
const NegativeIntegerModel = IntegerModel
.extend()
.assert(
...assertBoundedUpper(
IntegerModel,
0,
false,
compare
)
)
.as('NegativeInteger')
NegativeIntegerModel(-1) //=> -1
NegativeIntegerModel(0) //=> EXCEPTION: 'Value must be < 0 (got: 0)'
NegativeIntegerModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'() → [(* → Boolean), String]2-element array [Function, String]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if the input is emptyfalse if the input is NOT emptyThe second element is a fixed error string to return when the input is NOT empty.
'use strict'
const isString = require('@eluvio/elv-js-helpers/Boolean/isString')
const StringModel = require('@eluvio/elv-js-helpers/Model/StringModel')
const assertAfterCheck = require('@eluvio/elv-js-helpers/ModelAssertion/assertAfterCheck')
const assertEmpty = require('@eluvio/elv-js-helpers/ModelAssertion/assertEmpty')
// Note use of spread operator (...) to unpack the arrays returned by assertAfterCheck() and assertEmpty()
const EmptyStringModel = StringModel.extend()
.assert(
...assertAfterCheck(
isString,
...assertEmpty
)
)
.as('EmptyString')
EmptyStringModel('foo') //=> EXCEPTION: 'Value must be empty (got: "foo")'
EmptyStringModel('') //=> ''
EmptyStringModel([]) //=> EXCEPTION: 'expecting String, got Array []'String → ((Boolean, *, String) → String)msgError message describing the assertion condition that was not met
Returns a function to be called by ObjectModel to construct an error message when a particular assertion fails during validation.
Pass in a string describing the condition that was not met, e.g. 'must equal 42', and you will get back a function can be used to generate a full error message at runtime.
If the assertion that was passed in as the first argument to ObjectModel.assert() fails, the error message
generating function will be called with the assertion result (generally false), the failing value, and any
attribute name(s) that were traversed to access the value.
This allows the error message to include the attribute name (if available) and the bad value in the error message, e.g. 'Value must equal 42 (got: 43)'
'use strict'
const NumberModel = require('@eluvio/elv-js-helpers/Model/NumberModel')
const assertionErrMsg = require('@eluvio/elv-js-helpers/ModelAssertion/assertionErrMsg')
const AnswerToEverythingModel = NumberModel.extend()
.assert(
x => x === 42,
assertionErrMsg('must equal 42')
)
.as('AnswerToEverything')
AnswerToEverythingModel(43) //=> EXCEPTION: 'Value must equal 42 (got: 43)'((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → RegExp → [(* → Boolean), ObjectModelErrMsgFn]modelThe Model to add regex validation to
regexThe regex that must be matched.
errMsgOptional custom error message
2-element array [Function, Function]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if the input matches the specified regex OR the input is not a valid instance of the specified Model to be boundedfalse if the input is a valid instance of the specified Model AND fails to match the specified regex.This means that the assertion will PASS if the input is not a valid instance of the Model to be bounded. The purpose of this is to prevent redundant errors, e.g. 42 is not a String, 42 must match regex /^[a-z]+$/.
The second element is a function to be called by ObjectModel to construct an error message if the bounds validation fails.
'use strict'
const StringModel = require('@eluvio/elv-js-helpers/Model/StringModel')
const assertMatchesRegex = require('@eluvio/elv-js-helpers/ModelAssertion/assertMatchesRegex')
// Note use of spread operator (...) to unpack the array returned by _assertBoundedUpper()
const UUIDStringModel = StringModel.extend()
.assert(
...assertMatchesRegex(
StringModel,
/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/,
'is not in UUID format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx')
)
.as('UUIDString')
UUIDStringModel('12345678-1234-1234-1234-123456789abc') //=> '12345678-1234-1234-1234-123456789abc'
UUIDStringModel('foo') //=> EXCEPTION: 'Value is not in UUID format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (got: "foo")'
UUIDStringModel(42) //=> EXCEPTION: 'expecting String, got Number 42'((Boolean, *, String) → String) ObjectModelErrMsgFn => ((*, *) → Boolean) → (Function | String) → [([*] → Boolean), ObjectModelErrMsgFn | String]checkFnA 2-input function that returns true if the inputs are considered to be compatible,
false otherwise.
errStrOrFnError message to use when ordering check fails.
2-element array [Function, Function]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element returned is a function that will take an input and return:
true if all neighboring elements in input return true when fed into checkFn OR the input is not arrayfalse if the input is an array AND has at least one pair of neighboring elements that cause checkFn to return false.This means that the assertion will PASS if the input is not a valid Array. The purpose of this is to prevent redundant errors, e.g. 'foo' is not an Array, 'foo' has neighbors that are not compatible.
The second element returned is a function to be called by ObjectModel to construct an error message if the bounds validation fails.
Note that this function is equivalent to assertOrdered, but with orderingFn renamed to checkFn.
'use strict'
const assertNeighborsPass = require('@eluvio/elv-js-helpers/ModelAssertion/assertNeighborsPass')
const defBasicModel = require('@eluvio/elv-js-helpers/ModelFactory/defBasicModel')
const kind = require('@eluvio/elv-js-helpers/Validation/kind')
// Note use of spread operator (...) to unpack the array returned by assertNeighborsPass()
const ArrayAllSameKindModel = defBasicModel('ArrayAllSameKindModel', Array).extend()
.assert(
...assertNeighborsPass(
(x, y) => kind(x) === kind(y),
'elements are not all of the same kind'
)
)
ArrayAllSameKindModel([1, 2, 3]) //=> [1, 2, 3]
ArrayAllSameKindModel([]) //=> []
ArrayAllSameKindModel([42, 'a']) //=> EXCEPTION: 'Value elements are not all of the same kind (got: [42,"a"])'
ArrayAllSameKindModel('foo') //=> EXCEPTION: 'expecting Array, got String "foo"'() → [(* → Boolean), String]2-element array [Function, String]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if the input is NOT emptyfalse if the input is emptyThe second element is a fixed error string to return when the input is empty.
'use strict'
const isString = require('@eluvio/elv-js-helpers/Boolean/isString')
const StringModel = require('@eluvio/elv-js-helpers/Model/StringModel')
const assertAfterCheck = require('@eluvio/elv-js-helpers/ModelAssertion/assertAfterCheck')
const assertNotEmpty = require('@eluvio/elv-js-helpers/ModelAssertion/assertNotEmpty')
// Note use of spread operator (...) to unpack the arrays returned by assertAfterCheck() and assertNotEmpty()
const NonEmptyStringModel = StringModel.extend()
.assert(
...assertAfterCheck(
isString,
...assertNotEmpty
)
)
.as('NonEmptyString')
NonEmptyStringModel('foo') //=> 'foo'
NonEmptyStringModel('') //=> EXCEPTION: 'Value must not be empty (got: "")'
NonEmptyStringModel([]) //=> EXCEPTION: 'expecting String, got Array []'() → [(* → Boolean), String]2-element array [Function, String]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The returned assertion will always pass, and the error message (which will never be used) is an empty string.
'use strict'
const assertNothing = require('@eluvio/elv-js-helpers/ModelAssertion/assertNothing')
const T = require('@eluvio/elv-js-helpers/Functional/T')
assertNothing() //=> [T, '']((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → * → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]keyModelThe Model to check keys against
2-element array [Function, Function]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if the input is an object and all the object's keys are valid instances of the specified Model OR the input is not a Javascript objectfalse if the input IS a Javascript object AND has a key (property name) that violates specified ModelThis means that the assertion will PASS if the input is not a Javascript object. The purpose of this is to prevent redundant errors, e.g. input is not an Object, property name 'foo' is invalid
The second element is a function to be called by ObjectModel to construct an error message if the bounds validation fails.
'use strict'
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
const assertObjKeysValid = require('@eluvio/elv-js-helpers/ModelAssertion/assertObjKeysValid')
const defBasicModel = require('@eluvio/elv-js-helpers/ModelFactory/defBasicModel')
// Note use of spread operator (...) to unpack the array returned by assertObjKeysValid()
const NoBlankKeysObjModel = defBasicModel('NoBlankKeysObj', Object)
.extend()
.assert(...assertObjKeysValid(NonBlankStrModel))
NoBlankKeysObjModel({' ': 3}) //=> EXCEPTION: 'invalid property name " " (is not a valid NonBlankString)'((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → * → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]valueModelThe Model to check values against
2-element array [Function, Function]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if input is an object and all the object's values are valid instances of the specified Model OR the input is not a Javascript objectfalse if the the input IS a Javascript object AND has a value that violates specified ModelThis means that the assertion will PASS if the input is not a Javascript object. The purpose of this is to prevent redundant errors, e.g. input is not an Object, property name 'foo' points to a value that is invalid
The second element is a function to be called by ObjectModel to construct an error message if the bounds validation fails.
'use strict'
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
const assertObjValuesValid = require('@eluvio/elv-js-helpers/ModelAssertion/assertObjValuesValid')
const defBasicModel = require('@eluvio/elv-js-helpers/ModelFactory/defBasicModel')
// Note use of spread operator (...) to unpack the array returned by assertObjValuesValid()
const NoBlankStringValsObjModel = defBasicModel('NoBlankStringValsObj', Object)
.extend()
.assert(...assertObjValuesValid(NonBlankStrModel))
NoBlankStringValsObjModel({foo: ' '}) //=> EXCEPTION: 'key "foo" points to a value that is an invalid NonBlankString (NonBlankString: Value must not be a blank string (got: " "))'((Boolean, *, String) → String) ObjectModelErrMsgFn => ((*, *) → Boolean) → (Function | String) → [([*] → Boolean), ObjectModelErrMsgFn | String]orderingFnA 2-input function that returns true if the inputs are considered to be in order,
false otherwise. Note that this function could check for ascending or descending order, and allow or disallow duplicates.
It could also check for any arbitrary pair-wise condition to be considered 'ordered', but the most common case is
checking whether an array is sorted or not.
errStrOrFnError message to use when ordering check fails.
2-element array [Function, Function]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element returned is a function that will take an input and return:
true if the input is ordered OR the input is not arrayfalse if the input is an array AND is not ordered.This means that the assertion will PASS if the input is not a valid array. The purpose of this is to prevent redundant errors, e.g. 'foo' is not an Array, 'foo' is not sorted.
The second element returned is a function to be called by ObjectModel to construct an error message if the bounds validation fails.
Whether the array is ordered or not is determined by orderingFn, a function that takes two inputs and returns
true if the inputs are in order or false otherwise.
Note that this function is equivalent to assertNeighborsPass, but with checkFn renamed to orderingFn.
'use strict'
const assertOrdered = require('@eluvio/elv-js-helpers/ModelAssertion/assertOrdered')
const defArrayModel = require('@eluvio/elv-js-helpers/ModelFactory/defArrayModel')
// Note use of spread operator (...) to unpack the array returned by assertOrdered()
const OrderedNumArrayModel = defArrayModel('OrderedArray', Number).extend()
.assert(
...assertOrdered(
(x, y) => x <= y,
'is not in ascending order'
)
).as('OrderedNumArray')
OrderedNumArrayModel([1, 2, 3]) //=> [1, 2, 3]
OrderedNumArrayModel([]) //=> []
OrderedNumArrayModel([3, 2]) //=> EXCEPTION: 'Value is not in ascending order (got: [3,2])'
OrderedNumArrayModel('foo') //=> EXCEPTION: 'expecting Array of Number, got String "foo"'((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → ((b, a) → Boolean) → String → String → String → [(* → Boolean), ObjectModelErrMsgFn | String]checkFnA 2-input function taking value of object's propertyName2 FIRST, then object's propertyName1 SECOND (this is to allow more intuitive use with the way isGT / isGTE etc are curried)
reqDescDescription of required relation, e.g. 'must be greater than' - this will be used in error messages e.g. 'propertyName1 must be greater than propertyName2'
propertyName1Name of attribute to check against propertyName2
propertyName2Name of attribute to check against propertyName1
2-element array [Function, Function | String]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if the input satisfies the specified property relationship OR the input is not an objectfalse if the input is an object AND violates the specified property relationshipThis means that the assertion will PASS if the input is not a valid instance of the Model to be bounded. The purpose of this is to prevent redundant errors, e.g. Value is not an Object, 'foo' must be greater than 'bar'.
The second element is either an error string or a function to generate an error message. If it is a function, it will
get called by ObjectModel when it validates a Model and fails, passing in the assertion result (generally false),
the failing value, and any attribute name(s) that were traversed to access the value.
'use strict'
const assertPropRel = require('@eluvio/elv-js-helpers/ModelAssertion/assertPropRel')
const defObjectModel = require('@eluvio/elv-js-helpers/ModelFactory/defObjectModel')
const isGTE = require('@eluvio/elv-js-helpers/Boolean/isGTE')
const NumLimitsModel = defObjectModel(
'NumberLimits',
{
min: Number,
max: Number
}
).extend().assert(
...assertPropRel(
isGTE,
'must be greater than or equal to',
'max',
'min'
)
)
NumLimitsModel({min:1, max:2}) //=> {min:1, max:2}
NumLimitsModel({min:2, max:1}) //=> EXCEPTION: 'max (1) must be greater than or equal to min (2)'((Boolean, *, String) → String) ObjectModelErrMsgFn => () → [(* → Boolean), ObjectModelErrMsgFn]2-element array [Function, Function]. See description for details.
Returns a 2-element array for use in an ObjectModel assertion
The first element is a function that will take an input and return:
true if the input can be parsed as UTC datetime string (yyyy:MM:ddThh:mm:ssZ) OR the input is not a valid instance of NonBlankStrModelfalse if the input is a valid instance of NonBlankStrModel AND fails to parse as a UTC datetime string.This means that the assertion will PASS if the input is not a valid NonBlankString. The purpose of this is to prevent redundant errors, e.g. 42 is not a String, 42 is not a valid ISO 8601 datetime string.
The second element is a function to be called by ObjectModel to construct an error message if the bounds validation fails.
'use strict'
const assertValidUTCStr = require('@eluvio/elv-js-helpers/ModelAssertion/assertValidUTCStr')
const StringModel = require('@eluvio/elv-js-helpers/Model/StringModel')
// Note use of spread operator (...) to unpack the array returned by _assertBoundedUpper()
const UTCDateTimeStringModel = StringModel.extend()
.assert(...assertValidUTCStr())
.as('UTCDateTimeString')
UTCDateTimeStringModel('2022-05-03T00:26:07Z') //=> '2022-05-03T00:26:07Z'
UTCDateTimeStringModel('2022-99-03T00:26:07Z') //=> EXCEPTION: 'Value is not a valid UTC datetime string (got: "2022-99-03T00:26:07Z")'
UTCDateTimeStringModel('foo') //=> EXCEPTION: 'Value is not a valid UTC datetime string (got: "foo")'String → Function → Object → ObjectpropThe name of the property to set
computeFnThe function to use to compute value of prop
objThe object to copy and use as input to computeFn
Returns a shallow copy of object with a specified property set to computeFn(obj)
Note that if obj is an ObjectModel instance the return value will be a plain
Javascript object without model constraints.
'use strict'
const assocComputed = require('@eluvio/elv-js-helpers/Functional/assocComputed')
assocComputed('bar', x => x.foo * 2, {foo: 2}) //=> {foo: 2, bar: 4}
// function is curried: call with fewer than 3 args to obtain a narrower function
const addTax = assocComputed('tax', x => x.price * 0.05)
addTax({product: 'towel', price: 1}) //=> {product: 'towel', price: 1, tax: 0.05}((e → (), a → ()) → ()) → Async e a((e → (), a → ()) → (() → ()) → Async e a(unnamed)A binary function that accepts 2 unary functions, and may return a function - if it returns a function, this will be called if the Async is cancelled. The Async will call the binary function, feeding in a reject function and a resolve function, to be called to signal completion of task.
Passthrough for the Async Crocks Algebraic Data Type
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Allows users of elv-js-helpers to create Async objects without adding the Crocks
package as a dependency.
const Async = require('@eluvio/elv-js-helpers/ADT/Async')String → Uint8ArraystrThe base-58 string to decode
The decoded bytes
Passthrough for the decode() function from the bs58 npm package.
(Copyright © 2018 cryptocoinjs, MIT License)
Decodes a base-58 string to a Uint8Array of the original bytes.
Throws an exception on bad input.
'use strict'
const base58Decode = require('@eluvio/elv-js-helpers/Conversion/base58Decode')
const bytes = base58Decode('2PDzvA279deFCZe2SV1B6NQQkDE')
const hexString = Buffer.from(bytes).toString('hex')
console.log(hexString) //=> OUTPUT: '01b6368fd21198ff5f97b00dc3918d6215bca039'String → Uint8ArraybytesThe bytes to encode
The base-58 string
Passthrough for the encode() function from the bs58 npm package.
(Copyright © 2018 cryptocoinjs, MIT License)
Encodes a Uint8Array, Buffer, or Array of bytes as a Base58 string.
Throws an exception on bad input.
'use strict'
const base58Encode = require('@eluvio/elv-js-helpers/Conversion/base58Encode')
const bytes = Uint8Array.from([
0, 60, 23, 110, 101, 155, 234,
15, 41, 163, 233, 191, 120, 128,
193, 18, 177, 179, 27, 77, 200,
38, 38, 129, 135
])
base58Encode(bytes) //=> '16UjcYNBG9GTK4uq2f7yYEbuifqCzoLMGS'
const hexString = '5b4b3f4c262aa0f5237cb9a4b59ab0825ddead28'
const hexBytes = Uint8Array.from(Buffer.from(hexString, 'hex'));
base58Encode(hexBytes) //=> '2GmbemxTtSdy1YeFWE6zg6CmG8wy'* → String | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is a non-blank Base58-encoded string.
If input passes validations, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const Base58StrModel = require('@eluvio/elv-js-helpers/Model/Base58StrModel')
Base58StrModel('foo') //=> 'foo'
Base58StrModel('FOO') //=> EXCEPTION: 'Value is not a valid Base58 string (got: "FOO")'
Base58StrModel(' ') //=> EXCEPTION: 'Value must not be a blank string (got: " ")'
Base58StrModel(42) //=> EXCEPTION: 'expecting String, got Number 42'[Boolean] → IntegerboolArrayAn array of booleans representing binary digits of a non-negative integer (most significant bit first)
Converts an array of booleans to a number by interpreting them as binary digits (most significant bits first)
'use strict'
const boolsToInt = require('@eluvio/elv-js-helpers/Conversion/boolsToInt')
boolsToInt([false, false, true]) //=> 1
boolsToInt([true, false]) //=> 2
boolsToInt([true, true, true]) //=> 7() → StringReturns the name of the (non-node-module) function that was responsible for current function getting called (
'current function' meaning the one containing the callerFuncName() call).
'use strict'
const currentFuncName = require('@eluvio/elv-js-helpers/Misc/currentFuncName')
const callerFuncName = require('@eluvio/elv-js-helpers/Misc/callerFuncName')
const MyFunc = () => console.log('Function: ' + currentFuncName() + ' was called by: ' + callerFuncName())
const OuterFunc = () => MyFunc()
OuterFunc() //=> OUTPUT: 'Function: MyFunc was called by: OuterFunc'(a → m b) → m a → m b(unnamed)A curried function that takes a 'normal' value and returns a wrapped value)
(unnamed)Instance of Functional data type to pass into function
The wrapped result
Passthrough for the chain() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Provides a pointfree way to call .chain() on a value wrapped in a Functional data type.
Given a curried function that takes a 'normal' value and returns a wrapped value, chain will convert it into a function that takes a wrapped value. The returned value will not gain an extra layer of wrapping from the input.
'use strict'
const chain = require('@eluvio/elv-js-helpers/Functional/chain')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
const map = require('@eluvio/elv-js-helpers/Functional/map')
// function has only one input, not need to curry
const reciprocal = a => a === 0 ? Err(['division by zero']) : Ok(1/a)
const ok4 = Ok(4)
const ok0 = Ok(0)
const badNum = Err(['failed to read input'])
reciprocal(4).inspect() //=> 'Ok 0.25'
reciprocal(0).inspect() //=> 'Err [ "division by zero" ]'
// passing in a wrapped value results in NaN (reciprocal does not know to unwrap value before use)
reciprocal(ok4).inspect() //=> 'Ok NaN'
// chain() asks input wrapper to remove wrapping and pass value to function, then does not re-wrap the (wrapped) return value
chain(reciprocal, ok4).inspect() //=> 'Ok 0.25'
// reciprocal gets value 0 and returns Err
chain(reciprocal, ok0).inspect() //=> 'Err [ "division by zero" ]'
// badNum ignores request to apply reciprocal()
chain(reciprocal, badNum).inspect() //=> 'Err [ "failed to read input" ]'
// compare to map - (which does not specify that result should not be re-wrapped)
// return value is wrapped twice, once by reciprocal and once by ok4
map(reciprocal, ok4).inspect() //=> 'Ok Ok 0.25'
// chain is curried, it is possible to call with only the first argument to return a new function
const wrappedReciprocal = chain(reciprocal)
wrappedReciprocal(ok4).inspect() //=> 'Ok 0.25'* → *xthe item to clone
Modified version of Ramda's clone function (Copyright © Scott Sauyet and Michael Hurley)
Uses original item's constructor function when input is an object.
Used to preserve ObjectModel constraints.
'use strict'
const clone = require('@eluvio/elv-js-helpers/Functional/clone')
const defObjectModel = require('@eluvio/elv-js-helpers/ModelFactory/defObjectModel')
const PersonNameModel = defObjectModel('PersonName', {first: String, last: String})
const arthur = PersonNameModel({first: 'Arthur', last:'Dent'})
const arthurClone = clone(arthur)
arthurClone.last = 'Clone'
console.log(arthurClone.last) //=> OUTPUT: 'Clone'
console.log(arthur.last) //=> OUTPUT: 'Dent'
arthurClone.last = 3 //=> EXCEPTION: 'expecting last to be String, got Number 3'[a] → [b] → -1 | 0 | 1xA string or an array whose elements can be compared with <
yA string or an array whose elements can be compared with <
-1 | 0 | 1
Compares two indexable items (generally arrays or strings) x and y pairwise and returns:
-1 if x can be considered 'less than' y (either x[i] < y[i] or y[i] is undefined for first pair x[i],y[i] where x[i] !== y[i])0 if x can be considered 'equal to' y (more specifically, if neither x < y nor y < x are true)1 if y can be considered 'less than' x (either y[i] < x[i] or x[i] is undefined for first pair x[i],y[i] where x[i] !== y[i])Used as an input into sorting and validation functions.
Throws an exception on bad inputs.
'use strict'
const cmpIndexable = require('@eluvio/elv-js-helpers/Functional/cmpIndexable')
cmpIndexable([], [42]) //=> -1
cmpIndexable([42], []) //=> 1
cmpIndexable([42], [42]) //=> 0
cmpIndexable([42, 1], [42]) //=> 1
cmpIndexable(2, 1) //=> EXCEPTION: 'cmpIndexable: first argument does not have a length'
cmpIndexable('abc', 'ab') //=> 1
cmpIndexable(null, undefined) //=> EXCEPTION: "Cannot read properties of null (reading 'length')"
cmpIndexable([42], ['a']) //=> EXCEPTION: 'cmpIndexable: elements at index 0 are not comparable'(a → a → Boolean) → (a → b → -1 | 0 | 1)fnthe 2-input function (returning Boolean) to use for testing inputs
Copies name and functionality of Ramda's comparator function (Copyright © Scott Sauyet and Michael Hurley)
When supplied with a boolean 2-input function f, will return another 2-input function that returns:
-1 if f(a, b) is true
1 if f(b, a) is true
0 otherwise
This function can be passed in as a compare function to e.g. Javascript's Array.sort() method.
'use strict'
const comparator = require('@eluvio/elv-js-helpers/Functional/comparator')
const isLT = require('@eluvio/elv-js-helpers/Boolean/isLT')
const isGT = require('@eluvio/elv-js-helpers/Boolean/isGT')
const compAscending = comparator(isGT)
const compDescending = comparator(isLT)
let data = [1, 42, -42, 0]
data.sort(compAscending)
console.log(data) //=> OUTPUT: [-42, 0, 1, 42]
data.sort(compDescending)
console.log(data) //=> OUTPUT: [42, 1, 0, -42]a → b → -1 | 0 | 1xA value that can be compared with <
yA value that can be compared with <
-1 | 0 | 1
Compares two items x and y using Javascript's
less than (<)
operator, and returns:
-1 if x < y1 if y < x0 otherwise (x and y may not be equal, e.g. null < undefined and undefined < null are both false)Used as an input into sorting and validation functions.
'use strict'
const compare = require('@eluvio/elv-js-helpers/Functional/compare')
compare(1, 2) //=> -1
compare(2, 2) //=> 0
compare(2, 1) //=> 1
compare('a', 'b') //=> -1
compare(null, undefined) //=> 0
compare(undefined, null) //=> 0
compare([1], 'a') //= -1a → b → -1 | 0 | 1str1A string representing a fraction or whole number
str2A string representing a fraction or whole number
-1 | 0 | 1
Compares two strings x and y using fraction.js
and returns:
-1 if x < y0 if x == y (more specifically, if neither x < y nor y < x are true)1 if y < xUsed as an input into sorting and validation functions.
'use strict'
const compareFracStr = require('@eluvio/elv-js-helpers/Functional/compareFracStr')
compareFracStr('1', '2') //=> -1
compareFracStr('1/2', '1/4') //=> 1
compareFracStr(2, 1) //=> EXCEPTION: 'expecting String, got Number 2'
compareFracStr('a', 'b') //=> EXCEPTION: 'Value must be a string in the form of a whole number or a fraction (got: "a")'
compareFracStr(null, undefined) //=> EXCEPTION: 'expecting String, got null'
compareFracStr(0.5, '1/2') //=> EXCEPTION: 'expecting String, got Number 0.5'(* → Boolean) → (* → Boolean) → (* → Boolean)preCheckFnA 1-input function - the precondition for checkFn to take place
checkFnA 1-input function - the actual check to perform
Creates a function that:
true if preCheckFn is false or checkFn is true.false if preCheckFn is true and checkFn is falseThe effect is that checkFn is only performed if preCheckFn is true.
If preCheckFn is false, checking is short-circuited and true is returned.
Generally used to skip irrelevant checks and avoid redundant errors in assertions, e.g. 'foo' is not a number + 'foo' must be > 0
'use strict'
const conditionalCheck = require('@eluvio/elv-js-helpers/Boolean/conditionalCheck')
const isString = require('@eluvio/elv-js-helpers/Boolean/isString')
const stringStartsWithF = conditionalCheck(isString, x => x.startsWith('f'))
// Skip assertion, value is not a string:
stringStartsWithF(1) //=> true
stringStartsWithF('foo') //=> true
stringStartsWithF('bar') //=> falsea → (() → a)(unnamed)The value to always return
Function that ignores any input and always returns the original value
Passthrough for the constant() Crocks combinator
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/functions/combinators.html#constant for more details.
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Given an input, returns a function that always returns that input.
'use strict'
const constant = require('@eluvio/elv-js-helpers/Functional/constant')
const always42 = constant(42)
always42() //=> 42() → StringReturns name of function that it is called from. Used for introspection/logging
'use strict'
const currentFuncName = require('@eluvio/elv-js-helpers/Misc/currentFuncName')
const MyFunc = () => console.log('Entered function: ' + currentFuncName())
MyFunc() //=> OUTPUT: 'Entered function: MyFunc'((a, b, …) → z) → a → b → … → z(unnamed)The function to curry
The curried function
Passthrough for the curry() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/functions/helpers.html#curry for more details.
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Currying converts a function that takes multiple arguments into one that can take fewer arguments and returns a function that can be supplied with the remaining arguments. This can be useful for creating a more specific function from a general function.
It is similar to defining a function using syntax like const mult = x => y => x * y, but allows calling the function
with the full list of arguments if desired (calling mult(2, 2) does not work when using the x => y => syntax).
Some functions like liftA2 and liftA2Join require a curried function as input.
'use strict'
const curry = require('@eluvio/elv-js-helpers/Functional/curry')
const withinBounds = (lower, upper, val) => (val >= lower) && (val <= upper)
// curry an already-defined function
const fromZeroToOne = curry(withinBounds)(0, 1) // returns a new function that takes 1 argument (val)
fromZeroToOne(0) //=> true
fromZeroToOne(42) //=> false
// curry the function during definition
const greaterThan = curry(
(lowerBound, val) => (val > lowerBound)
)
// function can be called normally with full set of arguments
greaterThan(0, 1) //=> true
// when called with only lowerBound, returns a new function that takes 1 argument (val)
const isPositive = greaterThan(0)
isPositive(0) //=> false
isPositive(42) //=> true* → Date | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is a Javascript Date
If input passes validation, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const DatetimeModel = require('@eluvio/elv-js-helpers/Model/DatetimeModel')
// when validation succeeds, returns the input:
const testVal = new Date('2022-01-01T07:30:00Z')
const myDatetime = DatetimeModel(testVal)
myDatetime.valueOf() //=> 1641022200000
DatetimeModel('foo') //=> EXCEPTION: 'expecting Date, got String "foo"'String → ([Model] | Model) → (* → Array | THROW)namethe name of the generated Model
defThe type/Model or array of types/Model that are valid for elements
Returns an ObjectModel that can be called with an input
Passthrough for ArrayModel() function from ObjectModel
(Copyright © 2015 Sylvain Pollet-Villard, MIT license) with name assignment added.
Returns an ObjectModel which will validate that an input is:
To define an array that can hold any type of value, pass in AnyModel for def.
'use strict'
const NonNegativeNumModel = require('@eluvio/elv-js-helpers/Model/NonNegativeNumModel')
const defArrayModel = require('@eluvio/elv-js-helpers/ModelFactory/defArrayModel')
const AgeArrayModel = defArrayModel('AgeArray', NonNegativeNumModel)
AgeArrayModel([42]) //=> [42]
AgeArrayModel([]) //=> []
AgeArrayModel(-1) //=> EXCEPTION: 'expecting Array of NonNegativeNumber, got Number -1'
AgeArrayModel([-1]) //=> EXCEPTION: 'Array[0] must be >= 0 (got: -1)'
AgeArrayModel('foo') //=> EXCEPTION: 'expecting Array of NonNegativeNumber, got String "foo"'
AgeArrayModel(['foo']) //=> EXCEPTION: 'expecting Array[0] to be Number, got String "foo"'String → ([Model] | Model) → (* → Array | THROW)namethe name of the generated Model
defThe type/Model or array of types/Model that are valid for input
Returns an ObjectModel that can be called with an input
Passthrough for BasicModel() function from ObjectModel
(Copyright © 2015 Sylvain Pollet-Villard, MIT license) with name assignment added.
Returns an ObjectModel which will validate that an input is of the specified type(s)
'use strict'
const defBasicModel = require('@eluvio/elv-js-helpers/ModelFactory/defBasicModel')
const StringModel = defBasicModel('String', String)
StringModel(42) //=> EXCEPTION: 'expecting String, got Number 42'
StringModel('foo') //=> 'foo'const defBoundedFracStrModel = require('@eluvio/elv-js-helpers/ModelFactory/defBoundedFracStrModel')String → (Number | null) → (Number | null) → (Boolean | null) → (Boolean | null) → (* → Model | THROW)namethe name of the generated Model
lowerBoundThe lower bound (a string that is a valid FracStringModel) that must be satisfied. If null, no lower bound will be checked.
upperBoundThe upper bound (a string that is a valid FracStringModel) that must be satisfied. If null, no upper bound will be checked.
lowerInclusiveIf true (and lowerBound is not null) then input is allowed to equal lowerBound.
upperInclusiveIf true (and upperBound is not null) then input is allowed to equal upperBound.
Returns an ObjectModel which will validate that an input is:
Note that it is possible to specify no bounds at all, in which case the returned Model will only check that input is a string representing a whole number or fraction.
Also note that bounds must be strings, e.g. '0', '22/7', '-42'.
'use strict'
const defBoundedFracStrModel = require('@eluvio/elv-js-helpers/ModelFactory/defBoundedFracStrModel')
const PositiveFracModel = defBoundedFracStrModel(
'PositiveFraction',
'0',
null,
false,
null
)
PositiveFracModel('42') //=> '42'
PositiveFracModel('22/7') //=> '22/7'
PositiveFracModel('0') //=> EXCEPTION: 'Value must be > 0 (got: "0")'
PositiveFracModel('-42') //=> EXCEPTION: 'Value must be > 0 (got: "-42")'
PositiveFracModel('foo') //=> EXCEPTION: 'Value must be a string in the form of a whole number or a fraction (got: "foo")'
PositiveFracModel(42) //=> EXCEPTION: 'expecting String, got Number 42'
const NegativeFracModel = defBoundedFracStrModel(
'NegativeFraction',
null,
'0',
null,
false
)
NegativeFracModel('42') //=> EXCEPTION: 'Value must be < 0 (got: "42")'
NegativeFracModel('0') //=> EXCEPTION: 'Value must be < 0 (got: "0")'
NegativeFracModel('-22/7') //=> '-22/7'
NegativeFracModel('-42') //=> '-42'
const FracZeroToOneModel = defBoundedFracStrModel(
'FractionZeroToOne',
'0',
'1',
true,
true
)
FracZeroToOneModel('1/2') //=> '1/2'String → (Number | null) → (Number | null) → (Boolean | null) → (Boolean | null) → (* → Integer | THROW)namethe name of the generated Model
lowerBoundThe lower bound that must be satisfied. If null, no lower bound will be checked.
upperBoundThe upper bound that must be satisfied. If null, no upper bound will be checked.
lowerInclusiveIf true (and lowerBound is not null) then input is allowed to equal lowerBound.
upperInclusiveIf true (and upperBound is not null) then input is allowed to equal upperBound.
Returns an ObjectModel that can be called with an input
Returns an ObjectModel which will validate that an input is:
Note that it is possible to specify no bounds at all, in which case the returned Model will only check that input is an integer.
'use strict'
const defBoundedIntModel = require('@eluvio/elv-js-helpers/ModelFactory/defBoundedIntModel')
const CartonEggCountModel = defBoundedIntModel('CartonEggCount', 0, 12, true, true)
CartonEggCountModel(-1) //=> EXCEPTION: 'Value must be >= 0 and <= 12 (got: -1)'
CartonEggCountModel(0) //=> 0
CartonEggCountModel(4.2) //=> EXCEPTION: 'Value must be an integer (got: 4.2)'
CartonEggCountModel(6) //=> 6
CartonEggCountModel(42) //=> EXCEPTION: 'Value must be >= 0 and <= 12 (got: 42)'
CartonEggCountModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'String → (Number | null) → (Number | null) → (Boolean | null) → (Boolean | null) → (* → Model | THROW)namethe name of the generated Model
lowerBoundThe lower bound that must be satisfied. If null, no lower bound will be checked.
upperBoundThe upper bound that must be satisfied. If null, no upper bound will be checked.
lowerInclusiveIf true (and lowerBound is not null) then input is allowed to equal lowerBound.
upperInclusiveIf true (and upperBound is not null) then input is allowed to equal upperBound.
Returns an ObjectModel which will validate that an input is:
Note that it is possible to specify no bounds at all, in which case the returned Model will only check that input is a number.
'use strict'
const defBoundedNumModel = require('@eluvio/elv-js-helpers/ModelFactory/defBoundedNumModel')
const HumanHeightMetersModel = defBoundedNumModel('HumanHeightMeters', 0, 3, false, true)
HumanHeightMetersModel(0) //=> EXCEPTION: 'Value must be > 0 and <= 3 (got: 0)'
HumanHeightMetersModel(1.5) //=> 1.5
HumanHeightMetersModel(4) //=> EXCEPTION: 'Value must be > 0 and <= 3 (got: 4)'
HumanHeightMetersModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'String → ([Model] | Model) → (* → Array | THROW)namethe name of the generated Model
defThe type/Model or array of types/Model that elements
Returns an ObjectModel that can be called with an input
Returns an ObjectModel which will validate that an input is:
To define an array that can hold any type of value, pass in AnyModel for def.
'use strict'
const defNonEmptyArrModel = require('@eluvio/elv-js-helpers/ModelFactory/defNonEmptyArrModel')
const NonNegativeNumModel = require('@eluvio/elv-js-helpers/Model/NonNegativeNumModel')
const NonEmptyAgeArrayModel = defNonEmptyArrModel('NonEmptyAgeArray', NonNegativeNumModel)
NonEmptyAgeArrayModel([42]) //=> [42]
NonEmptyAgeArrayModel([]) //=> EXCEPTION: 'Value must not be empty (got: [])'
NonEmptyAgeArrayModel(-1) //=> EXCEPTION: 'expecting Array of NonNegativeNumber, got Number -1'
NonEmptyAgeArrayModel([-1]) //=> EXCEPTION: 'Array[0] must be >= 0 (got: -1)'
NonEmptyAgeArrayModel('') //=> EXCEPTION: 'expecting Array of NonNegativeNumber, got String ""'
NonEmptyAgeArrayModel(['foo']) //=> EXCEPTION: 'expecting Array[0] to be Number, got String "foo"'const defNonEmptyTypedKVObjModel = require('@eluvio/elv-js-helpers/ModelFactory/defNonEmptyTypedKVObjModel')String → Model → Model → (* → Object | THROW)namethe name of the generated Model
keyModelThe Model to validate keys against
valueModelThe Model to validate values against
Returns an ObjectModel that can be called with an input
Returns an ObjectModel which will validate that an input is:
See also defTypedKVObjModel
'use strict'
const defNonEmptyTypedKVObjModel = require('@eluvio/elv-js-helpers/ModelFactory/defNonEmptyTypedKVObjModel')
const defObjectModel = require('@eluvio/elv-js-helpers/ModelFactory/defObjectModel')
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
const NonEmptyNonBlankKVModel = defNonEmptyTypedKVObjModel(
'NonEmptyNonBlankKV',
NonBlankStrModel,
NonBlankStrModel
)
NonEmptyNonBlankKVModel({}) //=> EXCEPTION: 'Value must have at least one entry (got: {})'
NonEmptyNonBlankKVModel({foo: 'bar'}) //=> {foo: 'bar'}
NonEmptyNonBlankKVModel({foo: ' '}) //=> EXCEPTION: 'key "foo" points to a value that is an invalid NonBlankString (NonBlankString: Value must not be a blank string (got: " "))'
NonEmptyNonBlankKVModel({' ': 'bar'}) //=> EXCEPTION: 'invalid property name " " (is not a valid NonBlankString)'
NonEmptyNonBlankKVModel({foo: 42}) //=> EXCEPTION: 'key "foo" points to a value that is an invalid NonBlankString (NonBlankString: expecting String, got Number 42)'
NonEmptyNonBlankKVModel(42) //=> EXCEPTION: 'expecting Object, got Number 42'
// When used for a field in an object, the error message will include the name of the field:
const MediaFileModel = defObjectModel(
"MediaFile",
{
streams: defNonEmptyTypedKVObjModel(
"streamsMap",
NonBlankStrModel,
defObjectModel(
"stream",
{
type: ["audio", "subtitle", "video"]
}
)
)
}
)
MediaFileModel({streams: {}}) //=> EXCEPTION: 'streams must have at least one entry (got: {})'String → Object → (* → Object | THROW)namethe name of the generated Model
defThe definition (field structure) of the Model to generate
Returns an ObjectModel that can be called with an input
Passthrough for ObjectModel() function from ObjectModel
(Copyright © 2015 Sylvain Pollet-Villard, MIT license) with name assignment added
Returns an ObjectModel which will validate that an input is:
Extra (i.e. unrecognized) fields are allowed. Use defSealedObjModel() instead if you wish to disallow.
'use strict'
const defObjectModel = require('@eluvio/elv-js-helpers/ModelFactory/defObjectModel')
const PersonNameModel = defObjectModel('PersonName', {first: String, last: String})
PersonNameModel(-1) //=> EXCEPTION: 'expecting Object, got Number -1'
PersonNameModel({first: 'Arthur', last: 'Dent'}) //=> {"first":"Arthur","last":"Dent"}
PersonNameModel({first: 'Arthur'}) //=> EXCEPTION: 'expecting last to be String, got undefined'
PersonNameModel({first: 'A', last: 'D', species: 'human'}) //=> {first: 'A', last: 'D', species: 'human'}const defRegexMatchedStrModel = require('@eluvio/elv-js-helpers/ModelFactory/defRegexMatchedStrModel')(String, RexExp, String | undefined) → (* → String | THROW)namethe name of the generated Model
regexThe regex that must be matched
errMsgOptional custom error message string (if omitted, regex will be included as part of standard error message)
Returns an ObjectModel that can be called with an input
Returns an ObjectModel which will validate that an input is:
'use strict'
const defRegexMatchedStrModel = require('@eluvio/elv-js-helpers/ModelFactory/defRegexMatchedStrModel')
const UUIDStringModel = defRegexMatchedStrModel('UUIDString', /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/)
UUIDStringModel('12345678-90ab-cdef-0123-4567890abcde') //=> '12345678-90ab-cdef-0123-4567890abcde'
UUIDStringModel('foo') //=> EXCEPTION: 'Value is not in valid format or contains illegal characters (must match regular expression: /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/) (got: "foo")'
UUIDStringModel(42) //=> EXCEPTION: 'expecting String, got Number 42'
// supply a nicer error message
const UUIDStringModel2 = defRegexMatchedStrModel(
'UUIDString',
/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/,
'is not in UUID format "xxxxxxxx-xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"'
)
UUIDStringModel2('foo') //=> EXCEPTION: 'Value is not in UUID format "xxxxxxxx-xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" (got: "foo")'String → Object → (* → Object | THROW)namethe name of the generated Model
defThe definition (field structure) of the Model to generate
Returns an ObjectModel that can be called with an input
Returns an ObjectModel which will validate that an input is:
The object returned by the function will also throw an exception if you attempt to add a field to it that is not in the original definition.
NOTE: Copying the object using a function like Ramda's assoc function will not preserve this protection for the copy.
'use strict'
const defSealedObjModel = require('@eluvio/elv-js-helpers/ModelFactory/defSealedObjModel')
const PersonNameModel = defSealedObjModel('PersonName', {first: String, last: String})
PersonNameModel(-1) //=> EXCEPTION: 'expecting Object, got Number -1'
PersonNameModel({first: 'Arthur', last: 'Dent'}) //=> {"first":"Arthur","last":"Dent"}
PersonNameModel({first: 'Arthur'}) //=> EXCEPTION: 'expecting last to be String, got undefined'
PersonNameModel({first: 'A', last: 'D', species: 'human'}) //=> EXCEPTION: 'Unrecognized property name(s): species'String → Model → Model → (* → Object | THROW)namethe name of the generated Model
keyModelThe Model to validate keys against
valueModelThe Model to validate values against
Returns an ObjectModel that can be called with an input
Returns an ObjectModel which will validate that an input is:
It offers similar validation capabilities as ObjectModel's MapModel but the resulting Model accepts a Javascript object as input and returns a (proxied) Javascript object as output.
'use strict'
const defTypedKVObjModel = require('@eluvio/elv-js-helpers/ModelFactory/defTypedKVObjModel')
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
const NoBlankKVModel = defTypedKVObjModel(
'NonBlankKV',
NonBlankStrModel,
NonBlankStrModel
)
NoBlankKVModel({}) //=> {}
NoBlankKVModel({foo: 'bar'}) //=> {foo: 'bar'}
NoBlankKVModel({foo: ' '}) //=> EXCEPTION: 'key "foo" points to a value that is an invalid NonBlankString (NonBlankString: Value must not be a blank string (got: " "))'
NoBlankKVModel({' ': 'bar'}) //=> EXCEPTION: 'invalid property name " " (is not a valid NonBlankString)'
NoBlankKVModel({foo: 42}) //=> EXCEPTION: 'key "foo" points to a value that is an invalid NonBlankString (NonBlankString: expecting String, got Number 42)'
NoBlankKVModel(42) //=> EXCEPTION: 'expecting Object, got Number 42'* → undefined (PRINTS TO CONSOLE)Pretty-prints value to console/stdout in JSON format. Like console.log(), returns undefined.
'use strict'
const dumpJSON = require('@eluvio/elv-js-helpers/Misc/dumpJSON')
dumpJSON('A') //=> OUTPUT: '"A"'
dumpJSON(42) //=> OUTPUT: '42'
dumpJSON(undefined) //=> OUTPUT: undefined
dumpJSON([1, 2, 3]) //=> OUTPUT: `[
// 1,
// 2,
// 3
// ]`
dumpJSON({foo: 'bar'}) //=> OUTPUT: `{
// "foo": "bar"
// }`
dumpJSON(dumpJSON) //=> OUTPUT: undefined(errVal → x) → (okVal → x) → Result errVal okVal → x(unnamed)The function to apply to value contained in an Err
(unnamed)The function to apply to value contained in an Ok
Function which takes a Result and returns output of one of the two supplied functions
Passthrough for the either() Crocks point-free function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/crocks/Result.html#either for more details on how to use with the Result ADT.
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Given two functions, returns a function that takes a Result and:
If the Result is an Err, calls the first function with the value wrapped by the Err If the Result is an Ok, calls the second function with the value wrapped by the Ok
'use strict'
const either = require('@eluvio/elv-js-helpers/Functional/either')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
const resultToString = either(
v => `Err result: (${v})`,
v => `Ok result: (${v})`
)
resultToString(Ok(100)) //=> 'Ok result: (100)'
resultToString(Err('fail')) //=> 'Err result: (fail)'a → Err axThe value to wrap in an Err
Passthrough for the Err variety of the Result Crocks Algebraic Data Type
(Copyright © 2016, Ian Hofmann-Hicks, ISC license), with automatic wrapping of non-array values to ensure proper
concatenation of Err objects.
See https://crocks.dev/docs/crocks/Result.html for more details.
Allows users of elv-js-helpers to create Err objects without adding the Crocks
package as a dependency, and following conventions of the elv-js-helpers package:
There are 2 kinds of Result objects, Ok and Err, that wrap successful and failed computations, respectively.
Result objects are useful for handling errors in functional pipelines and can collect multiple errors from various
branches of a workflow.
Normally, one does not create generic Result object instances, but rather Ok or Err instances.
'use strict'
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const curry = require('@eluvio/elv-js-helpers/Functional/curry')
const dumpJSON = require('@eluvio/elv-js-helpers/Misc/dumpJSON')
const liftA2 = require('@eluvio/elv-js-helpers/Functional/liftA2')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
const resultToPOJO = require('@eluvio/elv-js-helpers/Conversion/resultToPOJO')
const okObject = Ok(42)
// Non-array input automatically converted to 1-element array:
const errObject1 = Err('failed to obtain first input')
errObject1.inspect() //=> 'Err [ "failed to obtain first input" ]'
const errObject2 = Err(['failed to obtain second input'])
errObject2.inspect() //=> 'Err [ "failed to obtain second input" ]'
const mult = (a, b) => a * b
// convert function 'mult' into one that works with values wrapped in Ok / Err
const multResults = liftA2(curry(mult))
const goodResult = multResults(okObject, okObject)
goodResult.inspect() //=> 'Ok 1764'
dumpJSON(resultToPOJO(goodResult)) //=> OUTPUT: `{
// "ok": true,
// "value": 1764
// }`
multResults(errObject1, okObject).inspect() //=> 'Err [ "failed to obtain first input" ]'
multResults(okObject, errObject2).inspect() //=> 'Err [ "failed to obtain second input" ]'
const resultTwoBadInputs = multResults(errObject1, errObject2)
resultTwoBadInputs.inspect() //=> 'Err [ "failed to obtain first input", "failed to obtain second input" ]'
dumpJSON(resultToPOJO(resultTwoBadInputs)) //=> OUTPUT: `{
// "ok": false,
// "errMsgs": [
// "failed to obtain first input",
// "failed to obtain second input"
// ],
// "errors": [
// "failed to obtain first input",
// "failed to obtain second input"
// ]
// }`
Err([]) //=> EXCEPTION: 'Err cannot wrap an empty array'
Err([undefined]).inspect() //=> 'Err [ undefined ]'
dumpJSON(resultToPOJO(Err([undefined]))) //=> OUTPUT: `{
// "ok": false,
// "errMsgs": [
// "undefined"
// ],
// "errors": [
// null
// ]
// }`* → StringstrThe value to escape
Escapes a string for use in a RegExp.
Useful if you need to match slashes and other special characters.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
'use strict'
const escapeForRegExp = require('@eluvio/elv-js-helpers/Conversion/escapeForRegExp')
escapeForRegExp('foo') //=> 'foo'
escapeForRegExp('/') //=> '\/'
escapeForRegExp(42) //=> EXCEPTION: 'str.replace is not a function'Number → Number → Result [String] NumbertimeElapsedThe amount of Datetime taken so far
portionCompleteA number between 0 and 1 (inclusive) representing progress
Estimates remaining duration based on portion completed expressed as a number between 0 and 1 and Datetime elapsed The function is unit-agnostic, but for most uses timeElapsed would be in seconds.
Returns a Crocks Ok instance wrapping a number if calculation succeeds. Returns a Crocks Err instance wrapping an array containing error(s) if passed bad inputs.
'use strict'
const estRemainingDur = require('@eluvio/elv-js-helpers/Datetime/estRemainingDur')
const resultToPOJO = require('@eluvio/elv-js-helpers/Conversion/resultToPOJO')
estRemainingDur(21, 0.5).inspect() //=> 'Ok 21'
estRemainingDur(42, 1).inspect() //=> 'Ok 0'
const portionBadErr = estRemainingDur(42, 0)
resultToPOJO(portionBadErr).ok //=> false
resultToPOJO(portionBadErr).errMsgs //=> ['estRemainingDur: portionComplete must be > 0 and <= 1 (got: 0)']
const elapsedBadErr = estRemainingDur(0, .1)
resultToPOJO(elapsedBadErr).ok //=> false
resultToPOJO(elapsedBadErr).errMsgs //=> ['estRemainingDur: timeElapsed must be > 0 (got: 0)']
const bothBadErr = estRemainingDur(0, 0)
resultToPOJO(bothBadErr).ok //=> false
resultToPOJO(bothBadErr).errMsgs //=> ['estRemainingDur: portionComplete must be > 0 and <= 1 (got: 0)', 'estRemainingDur: timeElapsed must be > 0 (got: 0)']Number → Number → Result [String] NumbertimeElapsedThe amount of Datetime taken so far
portionCompleteA number between 0 and 1 (inclusive) representing progress
Estimates total duration based on portion completed expressed as a number between 0 and 1 and Datetime elapsed The function is unit-agnostic, but for most uses timeElapsed is in seconds.
Returns a Crocks Ok instance wrapping a number if calculation succeeds. Returns a Crocks Err instance wrapping an array containing error(s) if passed bad inputs.
'use strict'
const estTotalDur = require('@eluvio/elv-js-helpers/Datetime/estTotalDur')
const resultToPOJO = require('@eluvio/elv-js-helpers/Conversion/resultToPOJO')
estTotalDur(21, 0.5).inspect() //=> 'Ok 42'
estTotalDur(42, 1).inspect() //=> 'Ok 42'
const portionBadErr = estTotalDur(42, 0)
resultToPOJO(portionBadErr).ok //=> false
resultToPOJO(portionBadErr).errMsgs // => ['estTotalDur: portionComplete must be > 0 and <= 1 (got: 0)']
const elapsedBadErr = estTotalDur(0, .1)
resultToPOJO(elapsedBadErr).ok //=> false
resultToPOJO(elapsedBadErr).errMsgs //=> ['estTotalDur: timeElapsed must be > 0 (got: 0)']
const bothBadErr = estTotalDur(0, 0)
resultToPOJO(bothBadErr).ok //=> false
resultToPOJO(bothBadErr).errMsgs //=>['estTotalDur: portionComplete must be > 0 and <= 1 (got: 0)', 'estTotalDur: timeElapsed must be > 0 (got: 0)']Number → StringsecondsLeftThe number of seconds remaining until completion
Returns an ETA expressed as number of days/hours/minutes/seconds remaining, based on a supplied value for how many seconds are left.
Unneeded larger units are omitted, and zero padding is suppressed for first number.
If secondsLeft is negative, returns '--'
'use strict'
const etaDurStr = require('@eluvio/elv-js-helpers/Datetime/etaDurStr')
etaDurStr(0) //=> "0s"
etaDurStr(1) //=> "1s"
etaDurStr(61) //=> "1m 01s"
etaDurStr(3661) //=> "1h 01m 01s"
etaDurStr(90061) //=> "1d 01h 01m 01s"
etaDurStr(954061) //=> "11d 01h 01m 01s"
etaDurStr(-1) //=> "--"Date → Number → StringcurrentTimeJavascript Date object to use as current Datetime.
secondsLeftThe number of seconds remaining until completion
zoneThe Datetime zone in which to express ETA
localesThe locale to use to format ETA
Returns an ETA Datetime or Datetime string based on a supplied value for current Datetime and how many seconds are left.
The return string will include the month and day only if the ETA has a different date than currentTime (within the
specified Datetime zone)
If secondsLeft is negative, returns '--'
Otherwise,
currentTime / zone will return 'Invalid DateTime'locales will be ignored, and if none are recognized, it will be obtained from the system environment.locales will cause an exception.'use strict'
const etaTimeStr = require('@eluvio/elv-js-helpers/Datetime/etaTimeStr')
const myTime = new Date('2022-01-01T07:30:00Z')
etaTimeStr(myTime, 10, 'America/Los_Angeles', 'en-US') //=> "11:30:10 PM PST"
etaTimeStr(myTime, 3600, 'America/Los_Angeles', 'en-US') //=> "Jan 1, 12:30:00 AM PST"
etaTimeStr(myTime, -10, 'America/Los_Angeles', 'en-US') //=> "--"
etaTimeStr(myTime, 10, 'foo', 'en-US') //=> EXCEPTION: "Invalid time zone specified: foo"{} → afalse
Ignores input and always returns false.
Used for composing functional workflows, often indicating 'never'.
'use strict'
const F = require('@eluvio/elv-js-helpers/Functional/F')
F(42) //=> false
F() //=> falseModel → * → BooleanModelThe Model to test against
inputThe value to test
Returns true if the specified Model fails to validate an input, false otherwise.
Used when the caller does not care about the details of why the input failed validation.
'use strict'
const failsModelCheck = require('@eluvio/elv-js-helpers/Boolean/failsModelCheck')
const PositiveIntModel = require('@eluvio/elv-js-helpers/Model/PositiveIntModel')
failsModelCheck(PositiveIntModel, 1) //=> false
failsModelCheck(PositiveIntModel, -1) //=> true
// function is curried: call with just first param to obtain a narrower function
const isNotPositiveInt = failsModelCheck(PositiveIntModel)
isNotPositiveInt(1) //=> false
isNotPositiveInt(0) //=> true
isNotPositiveInt('foo') //=> true((*) → *) → [*] → [*](unnamed)the test function, accepting a list element and returning a truthy value if the element should be included in result list
(unnamed)an iterable list of elements
The elements where function evaluated
Passthrough for Ramda's filter function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Tests elements of a list with a function and returns a new list containing the elements where the function evaluates to a truthy value.
'use strict'
const filter = require('@eluvio/elv-js-helpers/Functional/filter')
const arrOfInt = [1, 2, 3, 4, 5]
const isEven = a => a % 2 === 0
filter(isEven, arrOfInt) //=> [2, 4]
// Function is curried, call with fewer arguments to get a new, more specific function
const isOdd = a => a % 2 === 1
const filterOdd = filter(isOdd)
filterOdd(arrOfInt) //=> [1, 3, 5]((*) → *) → [*] → *(unnamed)the test function, accepting a list element and returning a truthy value if the element satisfies condition
(unnamed)an iterable list of elements
The first element that satisfies condition, or undefined if no element does
Passthrough for Ramda's find function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns first element of a list where test function evaluates to a truthy value.
'use strict'
const find = require('@eluvio/elv-js-helpers/Functional/find')
const isGTE = require('@eluvio/elv-js-helpers/Boolean/isGTE')
const arrOfInt = [1, 2, 3, 4, 5]
const isEven = a => a % 2 === 0
const gte10 = isGTE(10)
find(isEven, arrOfInt) //=> 2
find(gte10, arrOfInt) //=> undefined
// Function is curried, call with fewer arguments to get a new, more specific function
const isOdd = a => a % 2 === 1
const firstOdd = find(isOdd)
firstOdd(arrOfInt) //=> 1List → Listxthe list to flatten
The flattened list
Passthrough for Ramda's flatten function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns a new list by pulling every item out of it (and all its sub-arrays) and putting them in a new array, depth-first.
'use strict'
const flatten = require('@eluvio/elv-js-helpers/Functional/flatten')
flatten([1, [2, [3]]]) //=> [1, 2, 3]
flatten("abc") //=> ['a', 'b', 'c'](a → b → c) → b → a → c(unnamed)A 2-input function
Passthrough for the flip() Crocks combinator
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/functions/combinators.html#flip for more details.
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Given a 2-input function, returns a new function with the order of inputs reversed.
'use strict'
const flip = require('@eluvio/elv-js-helpers/Functional/flip')
const div = (a, b) => a/b
div(4, 2) //=> 2
const reciprocalDiv = flip(div)
reciprocalDiv(4, 2) //=> 0.5
// flip is curried, it is possible to call with all arguments at once
flip(div, 4, 2) //=> 0.5* → StringvalueThe value to format
Passthrough for the format() function from @ladjs/format-util
_(Copyright © 2015 Freeform Systems and other contributors, MIT license).
Allows users of elv-js-helpers to use the function without adding the @ladjs/format-util
package as a dependency.
Converts input to a string for use in error messages and log statements.
Similar to format() from the node:util module but without the code size
overhead of using that module.
'use strict'
const format = require('@eluvio/elv-js-helpers/Conversion/format')
format(' ') //=> '" "'
format(42) //=> '42'
format(x => x*2) //=> '[Function (anonymous)]'
format(format) //=> '[Function: format]'string → numberstrA string representing a fraction or whole number
Evaluates string as a rational number using fraction.js and converts to a number.
'use strict'
const fracStrToNum = require('@eluvio/elv-js-helpers/Conversion/fracStrToNum')
fracStrToNum('1') //=> 1
fracStrToNum('1/2') //=> 0.5
fracStrToNum(9) //=> EXCEPTION: 'expecting String, got Number 9'
fracStrToNum('1/0') //=> EXCEPTION: 'Value must be a string in the form of a whole number or a fraction (got: "1/0")'
fracStrToNum('0/1') //=> 0String | Number → Object(unnamed)The value to convert into a fraction.js object
A fraction.js object
Passthrough for the fraction.js constructor (Copyright © 2017 Robert Eisele, MIT license)
See https://www.npmjs.com/package/fraction.js for more details.
Provided for convenience and to encourage standardization.
Accepts a number or string representation of a rational number and returns a fraction.js object.
'use strict'
const fraction = require('@eluvio/elv-js-helpers/Conversion/fraction')
fraction(4.2).toFraction(true) //=> '4 1/5'
fraction('foo').toFraction(true) //=> EXCEPTION: 'Invalid argument'
fraction('1/0').toFraction(true) //=> EXCEPTION: 'Division by Zero'
fraction(4.2).toFraction(true) //=> '4 1/5'
fraction('22/7').valueOf() //=> 3.142857142857143
// .s returns sign:
fraction('-22/7').s //=> -1
// .n returns numerator
fraction('-22/7').n //=> 22
// .d returns denominator
fraction('-22/7').d //=> 7
fraction('9 3/4').valueOf() //=> 9.75* → String | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is:
Leading zeroes are allowed, e.g. '001/002'
If input passes validations, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const FractionStrModel = require('@eluvio/elv-js-helpers/Model/FractionStrModel')
FractionStrModel('foo') //=> EXCEPTION: 'Value must be a string in the form of a whole number or a fraction (got: "foo")'
FractionStrModel(' ') //=> EXCEPTION: 'Value must be a string in the form of a whole number or a fraction (got: " ")'
FractionStrModel(42) //=> EXCEPTION: 'expecting String, got Number 42'
FractionStrModel('42') //=> '42'
FractionStrModel('0') //=> '0'
FractionStrModel('-42') //=> '-42'
FractionStrModel('42/2') //=> '42/2'
FractionStrModel('42/0') //=> EXCEPTION: 'Value must be a string in the form of a whole number or a fraction (got: "42/0")'Object → Number | EXCEPTIONfA fraction.js object
The Javascript number representation of the fraction
Convert a fraction.js object to a Javascript number. (fraction.js Copyright © 2017 Robert Eisele, MIT license)
See https://www.npmjs.com/package/fraction.js for more details.
Provided for use in function composition.
Accepts a fraction.js object and returns a Javascript number.
'use strict'
const fracToNum = require('@eluvio/elv-js-helpers/Conversion/fracToNum')
const fraction = require('@eluvio/elv-js-helpers/Conversion/fraction')
const myFraction = fraction(4.2)
fracToNum(myFraction) //=> 4.2
const pi = fraction('22/7')
fracToNum(pi) //=> 3.142857142857143
fracToNum('22/7') //=> EXCEPTION: 'Value is not a fraction.js object'List (Pair String a) → Object(unnamed)The List of key, value Pairs
Passthrough for the fromPairs() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/functions/helpers.html#frompairs for more details.
Creates an object from a Crocks List of Pair objects, with each Pair containing key as first element and value
as second element.
Not to be confused with Ramda's fromPairs() function, which takes a 2-level regular Javascript array as input.
See also objFromEntries, toPairs
'use strict'
const fromPairs = require('@eluvio/elv-js-helpers/Conversion/fromPairs')
const List = require('@eluvio/elv-js-helpers/ADT/List')
const Pair = require('@eluvio/elv-js-helpers/ADT/Pair')
const kvPairs = List([Pair('a', 1), Pair('b',2)])
fromPairs(kvPairs) //=> { a: 1, b: 2 }* → *(unnamed)Any input
The input
Validates that an input is a function
Idx = String | Int | Symbol => [Idx] → {a} → a | UndefinedpathArraythe path to retrieve, expressed as an array
objectthe object to retrieve path from
Value or undefined
Renamed passthrough for Ramda's path function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Gets value at specified path from object, or undefined if not found.
Supports negative numbers as indexes, to retrieve element counting from end of array
'use strict'
const getPath = require('@eluvio/elv-js-helpers/Functional/getPath')
const myObject = {foo: {bar: [1, 2, 3]}}
getPath(['foo'], myObject) //=> {bar: [1, 2, 3]}
getPath(['bar'], myObject) //=> undefined
getPath(['foo', 'bar', 0], myObject) //=> 1
getPath(['foo', 'bar', -1], myObject) //=> 3Idx = String | Int | Symbol => Idx → Object | Array → a | Undefinedpropthe property (or index) to retrieve
itemthe item to retrieve property or element from
Value or undefined
Renamed passthrough for Ramda's prop function (Copyright © Scott Sauyet and Michael Hurley)
Not to be confused with Crocks getProp(), which returns a Maybe
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Gets value of specified property or index from object, or undefined if not found.
Supports negative numbers as indexes, to retrieve element counting from end of array
'use strict'
const getProp = require('@eluvio/elv-js-helpers/Functional/getProp')
const myObject = {foo: {bar: [1, 2, 3]}}
getProp('foo', myObject) //=> {bar: [1, 2, 3]}
getProp('bar', myObject) //=> undefined
const myArray = [0, 1, 2]
getProp(0, myArray) //=> 0
getProp(-1, myArray) //=> 2
// function is curried, call with fewer arguments to obtain a more specific function
const getFoo = getProp('foo')
getFoo(myObject) //=> {bar: [1, 2, 3]}
const getFirst = getProp(0)
getFirst(myArray) //=> 0((*) → String | Int | Symbol) → [*] → [*](unnamed)the classifier function, accepting a list element and returning a valid object key (string, int or symbol)
(unnamed)an iterable list of elements
The object containing sublists grouped by return value of the classifier function
Passthrough for Ramda's groupBy function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Groups elements of a list by the return value of a classifier function and returns an object where the keys are the classifier function return values and the values are list of elements that evaluated to those return values.
'use strict'
const groupBy = require('@eluvio/elv-js-helpers/Functional/groupBy')
const values = [1, 2, [3], 'a', 'b', null]
const kind = require('@eluvio/elv-js-helpers/Validation/kind')
groupBy(kind, values) //=> {Array: [[3]], Number: [1, 2], null: [null], String: ['a','b']}Number → Number → NumberoldValuestarting (baseline) value
newValueending value for calculating growth amount
growth expressed as a proportion of the absolute value of the first value
Calculates change between 2 values, expressed as a proportion of the (absolute value of) first value, e.g.:
0 if both values are the same0.5 if second value is 50% bigger than the first value-0.5 if second value is 50% smaller than the first valueNote that if the first value is 0 the return value will be:
Infinity if the second value is positive-Infinity if the second value is negative0 if the second value is zeroNote that if the first value is negative, "growth" is defined as "becoming less negative", e.g. growth(-100, 0) == 1
'use strict'
const growth = require('@eluvio/elv-js-helpers/Math/growth')
// Positive starting value
growth(42, 420) //=> 9
growth(42, 84) //=> 1
growth(42, 63) //=> 0.5
growth(42, 42) //=> 0
growth(42, 21) //=> -0.5
growth(42, 0) //=> -1
growth(42, -42) //=> -2
// Negative starting value
growth(-42, -84) //=> -1
growth(-42, 0) //=> 1
growth(-42, 42) //=> 2
// Zero starting value
growth(0, 1) //=> Infinity
growth(0, 0) //=> 0
growth(0, -1) //=> -InfinityArray → BooleanarrThe value to test
Returns true if passed an array with no duplicate elements.
Returns false if passed an array that has duplicate element(s).
Throws error if passed anything but an array.
Uses _Set from Ramda (Copyright © Scott Sauyet and Michael Hurley) to determine whether two elements are equivalent, so should handle cyclical data structures, comparison of equivalent objects, functions, and so forth.
'use strict'
const hasNoDuplicates = require('@eluvio/elv-js-helpers/Boolean/hasNoDuplicates')
hasNoDuplicates([]) //=> true
hasNoDuplicates([1, 2, 3]) //=> true
hasNoDuplicates([1, 2, 2]) //=> false
hasNoDuplicates([[1, 2], [1, 2]]) //=> false
hasNoDuplicates([[1, 2], [2, 1]]) //=> true
hasNoDuplicates([[1, 1], [2, 2]]) //=> true
hasNoDuplicates([{a:1, b:2}, {b:2, a:1}]) //=> false
hasNoDuplicates('foo') //=> EXCEPTION: 'hasNoDuplicates() - expecting Array, got: String'[*] → * | undefined | EXCEPTIONString → String(unnamed)an iterable list of elements
First element of array or first character of string
Passthrough for Ramda's head function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns first element of a list or last character of a string, or undefined if there is no first element,
and empty string if there is no last character
'use strict'
const head = require('@eluvio/elv-js-helpers/Functional/head')
head([1, 2, 3, 4, 5]) //=> 1
head([1]) //=> 1
head([]) //=> undefined
head('abc') //=> 'a'
head('a') //=> 'a'
head('') //=> ''
// NOTE: bad data types are ignored
head(0) //=> undefined
head({foo: 'bar'}) //=> undefined
// undefined will produce an exception
head(undefined) //=> EXCEPTION: 'Cannot read properties of undefined'a → axThe input value
The input value
Given an input, returns that input. Used for composing functional workflows, often indicating 'no-op'.
'use strict'
const identity = require('@eluvio/elv-js-helpers/Functional/identity')
identity(42) //=> 42(a → boolean) → (a → b) → (a → b) → a → b(unnamed)The boolean test function
(unnamed)The function to apply to value if test function returns true
(unnamed)The function to apply to value if test function returns false
Function which takes a value and returns output of one of the latter two functions
Passthrough for the ifElse() Crocks point-free function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/functions/logic-functions.html#ifelse for more details.
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Given 3 functions (a boolean function and two additional functions), returns a function that takes a value and, if function1(value) is true, returns function2(value), else returns function3(value)
'use strict'
const ifElse = require('@eluvio/elv-js-helpers/Functional/ifElse')
const isEven = x => x % 2 === 0
const half = x => x/2
const triplePlusOne = x => 3 *x + 1
const collatz = ifElse(
isEven,
half,
triplePlusOne
)
collatz(3) //=> 10
collatz(10) //=> 5[*] → [*] | EXCEPTIONString → String(unnamed)an iterable list of elements
Array containing all but the last element, or String containing all but the last character
Passthrough for Ramda's init function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns all but the last element of a list or string
'use strict'
const init = require('@eluvio/elv-js-helpers/Functional/init')
init([1, 2, 3, 4, 5]) //=> [1, 2, 3, 4]
init([1]) //=> []
init([]) //=> []
init('abc') //=> 'ab'
init('a') //=> ''
init('') //=> ''
// NOTE: bad data types are ignored
init(0) //=> []
init({foo: 'bar'}) //=> []
// undefined will produce an exception
init(undefined) //=> EXCEPTION: 'Cannot read properties of undefined'* → Integer | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is:
If input passes validation, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const IntegerModel = require('@eluvio/elv-js-helpers/Model/IntegerModel')
IntegerModel(42) //=> 42
IntegerModel(4.2) //=> EXCEPTION: 'Value must be an integer (got: 4.2)'
IntegerModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'
IntegerModel(Infinity) //=> EXCEPTION: 'Value must be an integer (got: Infinity)'
IntegerModel(-Infinity) //=> EXCEPTION: 'Value must be an integer (got: -Infinity)'a → BooleanxThe value to test
Returns true if passed an array.
Returns false if passed anything else
'use strict'
const isArray = require('@eluvio/elv-js-helpers/Boolean/isArray')
isArray([1, 2, 3]) //=> true
isArray(1, 2, 3) //=> false
isArray('foo') //=> falsea → BooleanxThe value to test
Returns true if passed a valid Base58 string.
Returns false if passed anything else.
'use strict'
const isBase58String = require('@eluvio/elv-js-helpers/Boolean/isBase58String')
isBase58String('foo') //=> true
isBase58String('FOO') //=> false
isBase58String(1, 2, 3) //=> false
// extra arguments are ignored
isBase58String('foo', 2, 3) //=> truea → → Boolean(unnamed)The value to test
Passthrough for the Ramda isEmpty function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns true if a value is the empty value for its type, false otherwise.
'use strict'
const isEmpty = require('@eluvio/elv-js-helpers/Boolean/isEmpty')
isEmpty([42]) //=> false
isEmpty([]) //=> true
isEmpty('') //=> true
isEmpty(null) //=> false
isEmpty({}) //=> true
isEmpty({foo: 'bar'}) //=> falsea → BooleanxThe value to test
Compares 2 values using Javascript's Strict equality
operator (===)
Returns true if value1 === value2
Returns false otherwise
To compare two arrays or objects for equivalence, use isEquivalent instead.
'use strict'
const isEqual = require('@eluvio/elv-js-helpers/Boolean/isEqual')
isEqual(42, 42) //=> true
isEqual(42, '42') //=> false
isEqual([1], [1]) //=> false
// function is curried: can call with fewer params to obtain a more specific function:
const equals42 = isEqual(42)
equals42(0) //=> false
equals42(42) //=> truea → b → Boolean(unnamed)The first value to compare
(unnamed)The second value to compare
Renamed passthrough for the Ramda equals function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Compares two values for equivalence, meaning it can compare arrays, objects, and functions. Also handles cyclical data structures.
const isEquivalent = require('@eluvio/elv-js-helpers/Boolean/isEquivalent')
isEquivalent(42, 42) //=> true
isEquivalent(42, '42') //=> false
isEquivalent([42], [42]) //=> true
// element order matters for arrays
isEquivalent([1, 42], [1, 42]) //=> true
isEquivalent([1, 42], [42, 1]) //=> false
// property order in objects does not matter
const obj1 = {foo: 42, bar: 1}
const obj2 = {bar: 1, foo: 42}
isEquivalent(obj1, obj2) //=> true
// function is curried: can call with fewer params to obtain a more specific function:
const isEmptyObject = isEquivalent({})
isEmptyObject({}) //=> true
isEmptyObject(42) //=> falsea → BooleanxThe value to test
Returns true if passed a Crocks Err instance.
Returns false if passed anything else
'use strict'
const isErr = require('@eluvio/elv-js-helpers/Boolean/isErr')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
isErr(Err(['invalid query'])) //=> true
isErr(Ok(42)) //=> false
isErr('foo') //=> falsea → BooleanxThe value to test
Returns true if passed a fraction.js object.
fraction.js (Copyright © 2017 Robert Eisele, MIT license)
Returns false if passed anything else
'use strict'
const isFraction = require('@eluvio/elv-js-helpers/Boolean/isFraction')
const fraction = require('@eluvio/elv-js-helpers/Conversion/fraction')
const twoOverOne = fraction('2')
const sortOfPi = fraction('22/7')
isFraction(twoOverOne) //=> true
isFraction(sortOfPi) //=> true
isFraction(22/7) //=> false
isFraction(Infinity) //=> false
isFraction(NaN) //=> false
isFraction('foo') //=> falsea → BooleanxThe value to test
Returns true if passed a function.
Returns false if passed anything else
'use strict'
const isFunction = require('@eluvio/elv-js-helpers/Boolean/isFunction')
isFunction([1, 2, 3]) //=> false
isFunction(1, 2, 3) //=> false
isFunction('foo') //=> false
isFunction(isFunction) //=> truea → BooleanxThe value to test
Returns true if passed a GeneratorFunction.
Returns false if passed anything else
'use strict'
const isGeneratorFunction = require('@eluvio/elv-js-helpers/Boolean/isGeneratorFunction')
function* numbersUpTo(x) {
for (let i = 0; i < x; i++) {
yield i
}
}
isGeneratorFunction(numbersUpTo) //=> true
isGeneratorFunction(Math.round) //=> false
isGeneratorFunction(undefined) //=> false* → * → Boolean(unnamed)the first value to compare
(unnamed)the second value to compare
Returns true if SECOND input is greater than the FIRST input, false otherwise.
Note that this is the REVERSE of normal infix notation, as well as Ramda's gt function - this is to allow
more intuitive currying, e.g. isGreaterThan42 = isGT(42)
If called with fewer than 2 arguments, will return a partially applied function
Uses the Javascript Greater than
operator (>) to perform the comparison.
'use strict'
const isGT = require('@eluvio/elv-js-helpers/Boolean/isGT')
isGT(1, 42) //=> true
isGT(42, 1) //=> false
isGT(42, 42) //=> false
isGT(null, undefined) //=> false
isGT(undefined, null) //=> false
// function is curried: can call with fewer params to obtain a narrower function
const isPositive = isGT(0)
isPositive(-1) //=> false
isPositive(0) //=> false
isPositive(1) //=> true(* → *) → * → * → BooleanpreprocessFnfunction to use to preprocess inputs, to allow them to be compared with >
value1the first value to compare
value2the second value to compare
Preprocesses 2 inputs individually using a specified function, then compares them and returns true if SECOND input
is greater than the FIRST input, false otherwise.
Note that order of arguments for comparison is the reverse of Ramda's gt function, this is to allow more intuitive
currying.
The preprocessor function needs to make the inputs directly comparable using the standard > operator. (i.e. this
function does the equivalent of return preProcessorFn(value1) > preProcessorFn(value2)
If called with fewer than 3 arguments, will return a partially applied function
'use strict'
const isGTCustom = require('@eluvio/elv-js-helpers/Boolean/isGTCustom')
const strLength = str => str.length
const isLongerThan = isGTCustom(strLength)
isLongerThan('a', 'ab') //=> true
isLongerThan('ab', 'a') //=> false
// x.length returns undefined for x === 42, undefined > undefined returns false:
isLongerThan(42, 42) //=> false
isLongerThan(null, undefined) //=> EXCEPTION: "Cannot read properties of null (reading 'length')"
// function is curried: can call with more than 1 argument
// example: call with 2 args
const isLongerThan3Chars = isGTCustom(strLength, 'foo')
isLongerThan3Chars('bar') //=> false
isLongerThan3Chars('foobar') //=> true
// example: call with 3 args
isGTCustom(strLength, 'foo', 'bar') //=> false
isGTCustom(strLength, 'foo', 'foobar') //=> true* → * → Boolean(unnamed)the first value to compare
(unnamed)the second value to compare
Returns true if SECOND input is greater than or equal to the FIRST input, false otherwise.
Note that this is the REVERSE of normal infix notation, as well as Ramda's gte function - this is to allow
more intuitive currying, e.g. isAtLeast42 = isGTE(42)
If called with fewer than 2 arguments, will return a partially applied function
Uses the Javascript Greater than or equal
operator (>=) to perform the comparison.
'use strict'
const isGTE = require('@eluvio/elv-js-helpers/Boolean/isGTE')
isGTE(1, 42) //=> true
isGTE(42, 1) //=> false
isGTE(42, 42) //=> true
isGTE(null, undefined) //=> false
// function is curried: can call with fewer params to obtain a narrower function
const notNegative = isGTE(0)
notNegative(-1) //=> false
notNegative(0) //=> true
notNegative(1) //=> true* → * → Boolean(unnamed)the first value to compare
(unnamed)the second value to compare
Returns true if SECOND input is less than the FIRST input, false otherwise.
Note that this is the REVERSE of normal infix notation, as well as Ramda's lt function - this is to allow
more intuitive currying, e.g. isLessThan42 = isLT(42)
If called with fewer than 2 arguments, will return a partially applied function
Uses the Javascript Less than
operator (<) to perform the comparison.
'use strict'
const isLT = require('@eluvio/elv-js-helpers/Boolean/isLT')
isLT(42, 1) //=> true
isLT(1, 42) //=> false
isLT(42, 42) //=> false
isLT(null, undefined) //=> false
isLT(undefined, null) //=> false
// function is curried: can call with fewer params to obtain a narrower function
const isNegative = isLT(0)
isNegative(-1) //=> true
isNegative(0) //=> false
isNegative(1) //=> false* → * → Boolean(unnamed)the first value to compare
(unnamed)the second value to compare
Returns true if SECOND input is less than or equal to the FIRST input, false otherwise.
Note that this is the REVERSE of normal infix notation, as well as Ramda's lte function - this is to allow
more intuitive currying, e.g. isAtMost42 = isLTE(42)
If called with fewer than 2 arguments, will return a partially applied function
Uses the Javascript Less than or equal
operator (<=) to perform the comparison.
'use strict'
const isLTE = require('@eluvio/elv-js-helpers/Boolean/isLTE')
isLTE(42, 1) //=> true
isLTE(1, 42) //=> false
isLTE(42, 42) //=> true
isLTE(null, undefined) //=> false
isLTE(undefined, null) //=> false
// function is curried: can call with fewer params to obtain a narrower function
const notPositive = isLTE(0)
notPositive(-1) //=> true
notPositive(0) //=> true
notPositive(1) //=> false* → Booleanxthe item to check
Returns true if passed in a validation Model, false otherwise.
Note that a ModelFactory is not a Model, but the output of a ModelFactory is.
'use strict'
const isModel = require('@eluvio/elv-js-helpers/Boolean/isModel')
const defObjectModel = require('@eluvio/elv-js-helpers/ModelFactory/defObjectModel')
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
isModel(42) //=> false
isModel(NonBlankStrModel) //=> true
isModel(defObjectModel) //=> false
const PersonModel = defObjectModel('PersonName', {first: String, last: String})
isModel(PersonModel) //=> true
const validatedPerson = PersonModel({
first: 'Arthur',
last: 'Dent'
})
isModel(validatedPerson) //=> false* → Booleanvaluethe value to test
Returns true if value is null or undefined, otherwise returns false
Copies functionality of the Ramda function of the same name (Copyright © Scott Sauyet and Michael Hurley)
'use strict'
const isNil = require('@eluvio/elv-js-helpers/Boolean/isNil')
isNil() //=> true
isNil(undefined) //=> true
isNil(null) //=> true
isNil(42) //=> false
// extra argument ignored:
isNil(42, undefined) //=> false
// extra argument ignored:
isNil(undefined, 42) //=> truea → → Boolean(unnamed)The value to test
Negated version of the Ramda isEmpty function (Copyright © Scott Sauyet and Michael Hurley)
Returns false if a value is the empty value for its type, true otherwise.
'use strict'
const isNotEmpty = require('@eluvio/elv-js-helpers/Boolean/isNotEmpty')
isNotEmpty([42]) //=> true
isNotEmpty([]) //=> false
isNotEmpty('') //=> false
isNotEmpty(null) //=> true
isNotEmpty({}) //=> false
isNotEmpty({foo: 'bar'}) //=> truea → BooleanxThe value to test
Returns true if passed null.
Returns false if passed anything else
'use strict'
const isNull = require('@eluvio/elv-js-helpers/Boolean/isNull')
isNull(null) //=> true
isNull() //=> false
isNull(undefined) //=> false
isNull(0) //=> false
// extra arguments ignored:
isNull(1, null, null) //=> false
isNull('foo') //=> false
// extra argument ignored:
isNull(null, 3) //=> truea → BooleanxThe value to test
Returns true if passed a Number.
Returns false if passed anything else
'use strict'
const isNumber = require('@eluvio/elv-js-helpers/Boolean/isNumber')
isNumber(1) //=> true
isNumber(Infinity) //=> true
isNumber(NaN) //=> true
isNumber('foo') //=> falsea → BooleanxThe value to test
Returns true if passed an object.
Returns false if passed anything else
'use strict'
const isObject = require('@eluvio/elv-js-helpers/Boolean/isObject')
isObject([1, 2, 3]) //=> false
// extra argument ignored:
isObject(1, {foo: 'bar'}) //=> false
isObject('foo') //=> false
isObject({}) //=> true
// extra argument ignored:
isObject({foo: 'bar'}, 3) //=> trueString → * → BooleankindNameLower case string expected when value is passed to kind-of.
xThe value to test
Returns true if value is of the specified type, false otherwise.
The type is determined using the kind function.
'use strict'
const isOfKind = require('@eluvio/elv-js-helpers/Boolean/isOfKind')
isOfKind('Array', [1, 2, 3]) //=> true
isOfKind('Array', 1, 2, 3) //=> false
isOfKind('Array', 'foo') //=> falsea → BooleanxThe value to test
Returns true if passed a Crocks Ok instance.
Returns false if passed anything else
'use strict'
const isOk = require('@eluvio/elv-js-helpers/Boolean/isOk')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
isOk(Err(['invalid query'])) //=> false
isOk(Ok(42)) //=> true
isOk('foo') //=> falsea → BooleanxThe value to test
Returns true if passed a regular expression.
Returns false if passed anything else
'use strict'
const isRegExp = require('@eluvio/elv-js-helpers/Boolean/isRegExp')
isRegExp([1, 2, 3]) //=> false
// extra arguments ignored:
isRegExp(1, /foo/) //=> false
isRegExp(/foo/) //=> true
// extra argument ignored:
isRegExp(/foo/, 3) //=> truea → BooleanxThe value to test
Returns true if passed a Crocks Result instance.
Returns false if passed anything else
'use strict'
const isResult = require('@eluvio/elv-js-helpers/Boolean/isResult')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
isResult(Err(['invalid query'])) //=> true
isResult(Ok(42)) //=> true
isResult('foo') //=> falsea → BooleanxThe value to test
Returns true if passed a string.
Returns false if passed anything else
'use strict'
const isString = require('@eluvio/elv-js-helpers/Boolean/isString')
isString([1, 2, 3]) //=> false
// extra arguments ignored:
isString(1, 'foo', 'bar') //=> false
isString('foo') //=> true
// extra argument ignored:
isString('foo', 3) //=> truea → BooleanxThe value to test
Returns true if passed undefined.
Returns false if passed anything else
'use strict'
const isUndefined = require('@eluvio/elv-js-helpers/Boolean/isUndefined')
isUndefined() //=> true
isUndefined(undefined) //=> true
isUndefined(null) //=> false
// extra argument ignored:
isUndefined(1, undefined) //=> false
isUndefined('foo') //=> false
// extra argument ignored:
isUndefined(undefined, 3) //=> truea → Just a(unnamed)The value to wrap in a Just
Passthrough for the Just variety of the Maybe Crocks Algebraic Data Type
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/crocks/Maybe.html for more details.
Allows users of elv-js-helpers to create Just objects without adding the Crocks
package as a dependency.
There are 2 kinds of Maybe objects, Just and Nothing, that wrap successful and failed value retrievals, respectively.
Maybe objects are useful for handling errors in Functional pipelines where a value may not be found.
Normally, one does not create generic Maybe object instances, but rather Just or Nothing instances.
'use strict'
const Just = require('@eluvio/elv-js-helpers/ADT/Just')
Just(42).inspect() //=> 'Just 42'* → StringvalThe item to evaluate
Name of the item's type
Modifies the kind-of package (Copyright © 2020, Jon Schlinkert, MIT License) by applying PascalCase capitalization to kinds that have corresponding PascalCase Javascript names
'use strict'
const kind = require('@eluvio/elv-js-helpers/Validation/kind')
kind(undefined) //=> 'undefined'
kind(null) //=> 'null'
kind(true) //=> 'Boolean'
kind(Buffer.from(' ')) //=> 'Buffer'
kind(42) //=> 'Number'
kind('str') //=> 'String'
kind(arguments) //=> 'arguments'
kind({}) //=> 'Object'
kind(Object.create(null)) //=> 'Object'
kind(new Date()) //=> 'Date'
kind([1, 2, 3]) //=> 'Array'
kind(/foo/) //=> 'RegExp'
kind(new Error('error')) //=> 'Error'
kind(function () {}) //=> 'Function'
kind(function * () {}) //=> 'GeneratorFunction'
kind(Symbol('str')) //=> 'Symbol'
kind(new Map()) //=> 'Map'
kind(new WeakMap()) //=> 'WeakMap'
kind(new Set()) //=> 'Set'
kind(new WeakSet()) //=> 'WeakSet'
kind(new Int8Array()) //=> 'Int8Array'
kind(new Uint8Array()) //=> 'Uint8Array'
kind(new Uint8ClampedArray()) //=> 'Uint8ClampedArray'
kind(new Int16Array()) //=> 'Int16Array'
kind(new Uint16Array()) //=> 'Uint16Array'
kind(new Int32Array()) //=> 'Int32Array'
kind(new Uint32Array()) //=> 'Uint32Array'
kind(new Float32Array()) //=> 'Float32Array'
kind(new Float64Array()) //=> 'Float64Array'[*] → * | undefined | EXCEPTIONString → String(unnamed)an iterable list of elements
Last element of array or last character of string
Passthrough for Ramda's last function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns last element of a list or last character of a string, or undefined if there is no last element, and empty
string if there is no last character
'use strict'
const last = require('@eluvio/elv-js-helpers/Functional/last')
last([1, 2, 3, 4, 5]) //=> 5
last([1]) //=> 1
last([]) //=> undefined
last('abc') //=> 'c'
last('a') //=> 'a'
last('') //=> ''
// NOTE: bad data types are ignored
last(0) //=> undefined
last({foo: 'bar'}) //=> undefined
// undefined will produce an exception
last(undefined) //=> EXCEPTION: 'Cannot read properties of undefined'Applicative m => (a → b → c) → m a → m b → m c(unnamed)The 2-input curried function to lift
The lifted function
Passthrough for the liftA2() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/functions/helpers.html#lifta2 for more details.
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Lifting converts a function
that works with 'normal' values as inputs and outputs and converts it into a function that works with values
that are wrapped in a Functional data type (ADT) like Ok, Err, List, and Pair. The converted function will
also return a value wrapped in a Functional data type.
This adapts the function to be able to compose into Functional workflows, making it easier to add things like input validation, error collection, and asynchronous event handling to the function cleanly.
liftA2 specifically converts 2-input curried functions.
'use strict'
const liftA2 = require('@eluvio/elv-js-helpers/Functional/liftA2')
const curry = require('@eluvio/elv-js-helpers/Functional/curry')
const dumpJSON = require('@eluvio/elv-js-helpers/Misc/dumpJSON')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
const resultToPOJO = require('@eluvio/elv-js-helpers/Conversion/resultToPOJO')
// define a function that takes and returns 'normal' values:
const mult = (a, b) => a * b
mult(42, 42) //=> 1764
// convert function 'mult' into one that works with values wrapped in Functional data types
const liftedMult = liftA2(curry(mult))
// create a wrapped good input
const okObject = Ok(42)
// create 2 wrapped errors indicating input failures:
// non-array input automatically converted to single element array
const errObject1 = Err('failed to obtain first input')
const errObject2 = Err(['failed to obtain second input'])
const goodResult = liftedMult(okObject, okObject)
goodResult.inspect() //=> 'Ok 1764'
resultToPOJO(goodResult) //=> {ok: true, value: 1764}
// call lifted function using 1 bad input:
const badResult1 = liftedMult(errObject1, okObject)
resultToPOJO(badResult1).ok //=> false
resultToPOJO(badResult1).errMsgs //=> ['failed to obtain first input']
const badResult2 = liftedMult(okObject, errObject2)
resultToPOJO(badResult2).ok //=> false
resultToPOJO(badResult2).errMsgs //=> ['failed to obtain second input']
// call lifted function using 2 bad inputs:
const badResult3 = liftedMult(errObject1, errObject2)
resultToPOJO(badResult3).ok //=> false
resultToPOJO(badResult3).errMsgs //=> ['failed to obtain first input', 'failed to obtain second input']
dumpJSON(resultToPOJO(badResult3)) //=> OUTPUT: `{
// "ok": false,
// "errMsgs": [
// "failed to obtain first input",
// "failed to obtain second input"
// ],
// "errors": [
// "failed to obtain first input",
// "failed to obtain second input"
// ]
// }`
// liftA2 itself is curried, it can be called with 1-3 arguments as desired. If called with 3 arguments, it will
// immediately return the final result instead of returning a function.
liftA2(curry(mult), okObject, okObject).inspect() //=> 'Ok 1764'Function → Function(unnamed)A function which takes 2 'normal' values and returns a wrapped value (e.g. a Crocks Result)
New function which takes 2 wrapped values and returns a wrapped value
Converts a function which accepts 2 'normal' values and returns a wrapped value (i.e. an ADT) into a function that takes 2 wrapped values and returns a wrapped value.
This is similar to the liftA2 function, except that it avoids adding an extra layer of wrapping to the returned value.
NOTE: The original function must be curried.
Note that the wrapper type of the inputs must be the same as the wrapper type returned by the function.
For example, if the original function returns a Maybe, then the inputs fed into the converted function must also be
Maybes (i.e. Just or Nothing)
If the original function returns a Result, then the inputs fed into the converted function must also be
Results (i.e. Ok or Err)
'use strict'
const liftA2Join = require('@eluvio/elv-js-helpers/Functional/liftA2Join')
const curry = require('@eluvio/elv-js-helpers/Functional/curry')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
// define a function that accepts 'normal' types as inputs and returns a wrapped type (an ADT)
const div = curry(
(x, y) => y === 0 ?
Err(['division by zero']) :
Ok(x / y)
)
// convert into a function that accepts wrapped types as inputs instead (and still returns a wrapped type)
const divWrapped = liftA2Join(div)
divWrapped(
Ok(42),
Ok(2)
).inspect() //=> 'Ok 21'
divWrapped(
Ok(42),
Ok(0)
).inspect() //=> 'Err [ "division by zero" ]'
divWrapped(
Err(['failed to read x']),
Ok(0)
).inspect() //=> 'Err [ "failed to read x" ]'
divWrapped(
Ok(42),
Err(['failed to read y'])
).inspect() //=> 'Err [ "failed to read y" ]'
divWrapped(
Err(['failed to read x']),
Err(['failed to read y'])
).inspect() //=> 'Err [ "failed to read x", "failed to read y" ]'Applicative m => (a → b → c → d) → m a → m b → m c → m d(unnamed)The 3-input curried function to lift
The lifted function
Passthrough for the liftA3() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/functions/helpers.html#lifta3 for more details.
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Lifting converts a function
that works with 'normal' values as inputs and outputs and converts it into a function that works with values
that are wrapped in a Functional data type (ADT) like Ok, Err, List, and Pair. The converted function will
also return a value wrapped in a Functional data type.
This adapts the function to be able to compose into Functional workflows, making it easier to add things like input validation, error collection, and asynchronous event handling to the function cleanly.
liftA3 specifically converts 3-input curried functions.
'use strict'
const liftA3 = require('@eluvio/elv-js-helpers/Functional/liftA3')
const curry = require('@eluvio/elv-js-helpers/Functional/curry')
const dumpJSON = require('@eluvio/elv-js-helpers/Misc/dumpJSON')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
const resultToPOJO = require('@eluvio/elv-js-helpers/Conversion/resultToPOJO')
// define a function that takes and returns 'normal' values:
const mult3 = (a, b, c) => a * b * c
mult3(42, 42, 42) //=> 74088
// convert function 'mult3' into one that works with values wrapped in Functional data types:
const liftedMult3 = liftA3(curry(mult3))
// create a wrapped good input
const okObject = Ok(42)
// create 2 wrapped errors indicating input failures:
// non-array input automatically converted to single element array
const errObject1 = Err('failed to obtain first input')
const errObject2 = Err(['failed to obtain second input'])
const goodResult = liftedMult3(okObject, okObject, okObject)
goodResult.inspect() //=> 'Ok 74088'
resultToPOJO(goodResult) //=> {ok: true, value: 74088}
// call lifted function using 1 bad input:
const badResult1 = liftedMult3(errObject1, okObject, okObject)
resultToPOJO(badResult1).ok //=> false
resultToPOJO(badResult1).errMsgs //=> ['failed to obtain first input']
const badResult2 = liftedMult3(okObject, errObject2, okObject)
resultToPOJO(badResult2).ok //=> false
resultToPOJO(badResult2).errMsgs //=> ['failed to obtain second input']
// call lifted function using 2 bad inputs:
const badResult3 = liftedMult3(errObject1, errObject2, okObject)
resultToPOJO(badResult3).ok //=> false
resultToPOJO(badResult3).errMsgs //=> ['failed to obtain first input', 'failed to obtain second input']
dumpJSON(resultToPOJO(badResult3)) //=> OUTPUT: `{
// "ok": false,
// "errMsgs": [
// "failed to obtain first input",
// "failed to obtain second input"
// ],
// "errors": [
// "failed to obtain first input",
// "failed to obtain second input"
// ]
// }`
// liftA3 itself is curried, it can be called with 1-4 arguments as desired. If called with 4 arguments, it will
// immediately return the final result instead of returning a function.
liftA3(curry(mult3), okObject, okObject, okObject).inspect() //=> 'Ok 74088'Function → Function(unnamed)A function which takes 3 'normal' values and returns a wrapped value (e.g. a Crocks Result)
New function which takes 3 wrapped values and returns a wrapped value
Converts a function which accepts 3 'normal' values and returns a wrapped value (i.e. an ADT) into a function that takes 3 wrapped values and returns a wrapped value.
This is similar to the liftA3 function, except that it avoids adding an extra layer of wrapping to the returned value.
NOTE: The original function must be curried.
Note that the wrapper type of the inputs must be the same as the wrapper type returned by the function.
For example, if the original function returns a Maybe, then the inputs fed into the converted function must also be
Maybes (i.e. Just or Nothing)
If the original function returns a Result, then the inputs fed into the converted function must also be
Results (i.e. Ok or Err)
'use strict'
const liftA3Join = require('@eluvio/elv-js-helpers/Functional/liftA3Join')
const curry = require('@eluvio/elv-js-helpers/Functional/curry')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
// define a function that accepts 'normal' types as inputs and returns a wrapped type (an ADT)
const div3 = curry(
(x, y, z) => y === 0 || z === 0 ?
Err(['division by zero']) :
Ok(x / y / z)
)
// convert into a function that accepts wrapped types as inputs instead (and still returns a wrapped type)
const div3Wrapped = liftA3Join(div3)
div3Wrapped(
Ok(42),
Ok(3),
Ok(2)
).inspect() //=> 'Ok 7'
div3Wrapped(
Ok(42),
Ok(0),
Ok(2)
).inspect() //=> 'Err [ "division by zero" ]'
div3Wrapped(
Err(['failed to read x']),
Ok(0),
Ok(2)
).inspect() //=> 'Err [ "failed to read x" ]'
div3Wrapped(
Ok(42),
Err(['failed to read y']),
Ok(2)
).inspect() //=> 'Err [ "failed to read y" ]'
div3Wrapped(
Err(['failed to read x']),
Err(['failed to read y']),
Err(['failed to read z'])
).inspect() //=> 'Err [ "failed to read x", "failed to read y", "failed to read z" ]'* → List *(unnamed)The value to wrap in a List
Passthrough for the List Crocks Algebraic Data Type
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Allows users of elv-js-helpers to create List objects without adding the Crocks
package as a dependency.
const List = require('@eluvio/elv-js-helpers/ADT/List')
const myList = List([1,2,3])
// List with 3 elements:
myList.inspect() //=> 'List [ 1, 2, 3 ]'
// Convert to Javascript array:
myList.toArray() //=> [ 1, 2, 3 ]
// head() returns instance of the Crocks 'Maybe' ADT: if array is empty, returns Nothing, else returns Just
myList.head().inspect() //=> 'Just 1'
// tail() returns an instance of Crocks 'Maybe' ADT, which wraps a List if there were at least 2 elements in original List
myList.tail().inspect() //=> 'Just List [ 2, 3 ]'
// List with 1 element, which itself is a 3-item array:
List([[1,2,3]]).inspect() //=> 'List [ [ 1, 2, 3 ] ]'
// List with 1 element:
List([42]).inspect() //=> 'List [ 42 ]'
List([42]).tail().inspect() //=> 'Nothing'
// Non-array input is treated as a single-element array:
List(42).inspect() //=> 'List [ 42 ]'
// List with 0 elements:
const emptyList = List([])
emptyList.inspect() //=> 'List [ ]'
// Instance of the Crocks 'Maybe' ADT, with no value
emptyList.head().inspect() //=> 'Nothing'List → * → ListlistA Crocks List object
elementThe item to add to end of list
New Crocks List containing original list elements plus new element at end
Returns a new Crocks List object with new element added to end
'use strict'
const listPush = require('@eluvio/elv-js-helpers/Functional/listPush')
const List = require('@eluvio/elv-js-helpers/ADT/List')
listPush(List([1,2,3]), 4).inspect() //=> 'List [ 1, 2, 3, 4 ]'(a → b) → m a → m b(unnamed)A curried function that takes a 'normal' value and returns a 'normal' value)
(unnamed)Instance of Functional data type to pass into function
The wrapped result
Passthrough for the map() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Not to be confused with the map function from Ramda, although functionality is similar.
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Provides a pointfree way to call .map() on a value wrapped in a Functional data type.
Given a curried function that takes a 'normal' value and returns another 'normal' value, map will convert it into a function that takes a wrapped value and returns a wrapped value.
'use strict'
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
const map = require('@eluvio/elv-js-helpers/Functional/map')
// function has only one input, not need to curry
const double = a => a * 2
const ok21 = Ok(21)
const badNum = Err(['failed to read input'])
double(21) //=> 42
// double() does not know to unwrap value before use:
double(ok21) //=> NaN
// map() asks input wrapper to remove wrapping and pass value to function, and then re-wrap the return value
map(double, ok21).inspect() //=> 'Ok 42'
// badNum ignores request to apply double()
map(double, badNum).inspect() //=> 'Err [ "failed to read input" ]'((String, *, Object) → *) → Object → ObjectfnThe function to execute to obtain new key
objThe object to process
Creates a new object with keys transformed by a function but values kept the same.
The function can have up to three inputs and will be passed current key, value, and the entire original object.
'use strict'
const mapObjKeys = require('@eluvio/elv-js-helpers/Functional/mapObjKeys')
const dumpJSON = require('@eluvio/elv-js-helpers/Misc/dumpJSON')
const myObj = {
firstname: "arthur",
lastname: "dent",
id: 42
}
// note that function can have fewer than 3 inputs if you don't need to use all of the parameters:
const keyPrefixer = key => `new_${key}`
const result = mapObjKeys(
keyPrefixer,
myObj
)
dumpJSON(result) //=> OUTPUT: '{\n "new_firstname": "arthur",\n "new_lastname": "dent",\n "new_id": 42\n}'((String, *, Object) → *) → ((*, String, Object) → *) → Object → ObjectkeyFnThe function to execute to obtain new key
valFnThe function to execute to obtain new value
objThe object to process
Creates a new object with top level keys and values transformed by separate functions.
The key transformation function can have up to three inputs and will be passed current KEY, current VALUE, and the entire original object.
The value transformation function can have up to three inputs and will be passed current VALUE, current KEY, and the entire original object.
'use strict'
const mapObjKV = require('@eluvio/elv-js-helpers/Functional/mapObjKV')
const dumpJSON = require('@eluvio/elv-js-helpers/Misc/dumpJSON')
const myObj = {
firstname: "arthur",
lastname: "dent",
id: 42
}
// note that function can have fewer than 3 inputs if you don't need to use all of the parameters:
const keyPrefixer = key => `new_${key}`
// note that function can have fewer than 3 inputs if you don't need to use all of the parameters:
const nameCapitalizer = (val, key) => key.endsWith('name')
? val.charAt(0).toUpperCase() + val.slice(1)
: val
const result = mapObjKV(
keyPrefixer,
nameCapitalizer,
myObj
)
dumpJSON(result) //=> OUTPUT: '{\n "new_firstname": "Arthur",\n "new_lastname": "Dent",\n "new_id": 42\n}'((*, String, Object) → *) → Object → ObjectfnThe function to execute to obtain new value
objThe object to process
Creates a new object with same keys as original object but with values transformed by specified function.
The function can have up to three inputs and will be passed current value, key, and the entire original object.
'use strict'
const mapObjValues = require('@eluvio/elv-js-helpers/Functional/mapObjValues')
const dumpJSON = require('@eluvio/elv-js-helpers/Misc/dumpJSON')
const myObj = {
firstname: "arthur",
lastname: "dent",
id: 42
}
// note that function can have fewer than 3 inputs if you don't need to use all of the parameters:
const nameCapitalizer = (val, key) => key.endsWith('name')
? val.charAt(0).toUpperCase() + val.slice(1)
: val
const result = mapObjValues(
nameCapitalizer,
myObj
)
dumpJSON(result) //=> OUTPUT: '{\n "firstname": "Arthur",\n "lastname": "Dent",\n "id": 42\n}'((*, Integer) → *) → Array → Array(unnamed)The function to apply to each (element, index) pair
(unnamed)The array to iterate over
Iterates over an array and passes (element, index) pair to supplied function to generate new array
'use strict'
const mapWithIndex = require('@eluvio/elv-js-helpers/Functional/mapWithIndex')
mapWithIndex((e,i) => `${e}-${i}`, ['a', 'b', 'c']) //=> ['a-0', 'b-1', 'c-2']
// function is curried: call with just 1 arg to obtain a narrower function
const addIndexSuffix = mapWithIndex((e,i) => `${e}-${i}`)
addIndexSuffix(['a', 'b', 'c']) //=> ['a-0', 'b-1', 'c-2']RegExp → * → Booleanrethe regexp to use to test
valuethe value to test
Returns true if second input is matches regex in first input, false otherwise.
If called with fewer than 2 arguments, will return a partially applied function
'use strict'
const matchesRegex = require('@eluvio/elv-js-helpers/Boolean/matchesRegex')
matchesRegex(/a/, 'abc') //=> true
matchesRegex(/a/, 'def') //=> false
matchesRegex(/a/, 0) //=> false
// function is curried: can call with fewer params to obtain a narrower function
const isThreeDigitNum = matchesRegex(/^[0-9]{3}$/)
isThreeDigitNum('123') //=> true
// Javascript does automatic type conversion in this case
isThreeDigitNum(123) //=> true
isThreeDigitNum('foo') //=> false
isThreeDigitNum('001') //=> true
isThreeDigitNum(1) //=> falseObject → Object → ObjectModified passthrough for Ramda's mergeRight function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Creates a new object with the top-level properties of the first object merged with the top-level properties from the second object. If a top-level key exists in both objects, the value from the first object will be replaced by the value from the second object.
Original object's constructor used to process merged data in order to preserve ObjectModel constraints on non-primitive models
'use strict'
const mergeRight = require('@eluvio/elv-js-helpers/Functional/mergeRight')
const defaults = {
children: ["DefaultChild1", "DefaultChild2"],
name: "Anonymous",
}
const moreData = {
age: 35,
children: ["Charlie"]
}
mergeRight(defaults, moreData) //=> {age: 35, children: ["Charlie"], name: "Anonymous"}
// function is curried: can call with fewer params to obtain a more specific function:
const ensureNameAndChildren = mergeRight(defaults)
ensureNameAndChildren({}) //=> {children: ["DefaultChild1", "DefaultChild2"], name: "Anonymous"}(a → Boolean) → (a → Boolean)(unnamed)A function that takes one input and returns a Boolean
A function that returns logically inverted output of the original function
Renamed passthrough for the not() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Takes a 1-input function and returns a negated version of the function, which will return false where the original
function returned true, and true where the original function returned false.
NOTE: This is not equivalent to using the Javascript NOT (!) operator, it returns a new function rather than returning negated result. It also is not suitable for negating functions with more than 1 input, as it will interfere with currying and the additional arguments.
'use strict'
const negate = require('@eluvio/elv-js-helpers/Functional/negate')
const isEmpty = a => a.length === 0
const isNotEmpty = negate(isEmpty)
isNotEmpty('foo') //=> true
isNotEmpty('') //=> false
isNotEmpty([]) //=> false
isNotEmpty([1, 2, 3]) //=> true
isNotEmpty(undefined) //=> EXCEPTION: "Cannot read properties of undefined (reading 'length')"((a, a) → Boolean) → Array → BooleancheckFn2-input function that returns true if the inputs pass check, false otherwise
arrayArray or other iterable with elements to check
Returns true if all pairs of neighbors in array return true when fed into checkFn.
Can be used to verify ordering, e.g. if checkFn is (x,y) => x <= y then array must be in ascending order.
'use strict'
const neighborsPass = require('@eluvio/elv-js-helpers/Boolean/neighborsPass')
const xGTEy = (x,y) => x <= y
neighborsPass(xGTEy, [1, 2, 2, 3]) //=> true
// single element, has no pairs to check:
neighborsPass(xGTEy, [1]) //=> true
neighborsPass(xGTEy, [3, 2, 2, 1]) //=> false
// strings support indexed access via []:
neighborsPass(xGTEy, 'abcde') //=> true
// non-array, has no pairs to check:
neighborsPass(xGTEy, 5) //=> true
// function is curried: call with 1 arg to obtain a narrower function
const isOrdered = neighborsPass(xGTEy)
isOrdered([1, 2, 2, 3]) //=> true
isOrdered([1]) //=> true
isOrdered([3, 2, 2, 1]) //=> false
// strings support indexed access via []:
isOrdered('abcde') //=> true
// non-array, has no pairs to check:
isOrdered(5) //=> true* → String | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is:
If input passes validations, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
NonBlankStrModel('foo') //=> 'foo'
NonBlankStrModel(' ') //=> EXCEPTION: 'Value must not be a blank string (got: " ")'
NonBlankStrModel(42) //=> EXCEPTION: 'expecting String, got Number 42'* → * | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is:
If input passes validations, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const NonNegativeIntModel = require('@eluvio/elv-js-helpers/Model/NonNegativeIntModel')
NonNegativeIntModel(42) //=> 42
NonNegativeIntModel(0) //=> 0
NonNegativeIntModel(4.2) //=> EXCEPTION: 'Value must be an integer (got: 4.2)'
NonNegativeIntModel(-1) //=> EXCEPTION: 'Value must be >= 0 (got: -1)'
NonNegativeIntModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'
NonNegativeIntModel(Infinity) //=> EXCEPTION: 'Value must be an integer (got: Infinity)'
NonNegativeIntModel(-Infinity) //=> EXCEPTION: 'Value must be an integer (got: -Infinity)'* → * | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is:
If input passes validations, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const NonNegativeNumModel = require('@eluvio/elv-js-helpers/Model/NonNegativeNumModel')
NonNegativeNumModel(42) //=> 42
NonNegativeNumModel(0) //=> 0
NonNegativeNumModel(-1) //=> EXCEPTION: 'Value must be >= 0 (got: -1)'
NonNegativeNumModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'
NonNegativeNumModel(Infinity) //=> Infinity
NonNegativeNumModel(-Infinity) //=> EXCEPTION: 'Value must be >= 0 (got: -Infinity)'() → NothingPassthrough for the Nothing variety of the Maybe Crocks Algebraic Data Type
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/crocks/Maybe.html for more details.
Allows users of elv-js-helpers to create Nothing objects without adding the Crocks
package as a dependency.
There are 2 kinds of Maybe objects, Just and Nothing, that wrap successful and failed value retrievals, respectively.
Maybe objects are useful for handling errors in Functional pipelines where a value may not be found.
Normally, one does not create generic Maybe object instances, but rather Just or Nothing instances.
'use strict'
const Nothing = require('@eluvio/elv-js-helpers/ADT/Nothing')
Nothing().inspect() //=> 'Nothing'
Nothing(42).inspect() //=> 'Nothing'() → DateReturns current datetime as a Javascript Date
'use strict'
const now = require('@eluvio/elv-js-helpers/Datetime/now')
const isGT = require('@eluvio/elv-js-helpers/Boolean/isGT')
const kind = require('@eluvio/elv-js-helpers/Validation/kind')
const currentDatetime = now()
kind(currentDatetime) //=> 'Date'
// later than 2022-12-02T16:53:20Z:
isGT(1670000000000, currentDatetime.valueOf()) //=> true() → StringReturns current datetime as a UTC string in ISO 8601 format YYYY-MM-DDTHH:MM:SSZ e.g. '2025-01-01T01:00:00Z'
'use strict'
const nowUTCStr = require('@eluvio/elv-js-helpers/Datetime/nowUTCStr')
const isGT = require('@eluvio/elv-js-helpers/Boolean/isGT')
const kind = require('@eluvio/elv-js-helpers/Validation/kind')
const currentUTCTimestamp = nowUTCStr()
kind(currentUTCTimestamp) //=> 'String'
// string value is larger (later) than 2025-01-01T01:00:00Z:
isGT('2025-01-01T01:00:00Z', currentUTCTimestamp) //=> true
currentUTCTimestamp.endsWith('Z') //=> true* → Number | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is a Javascript Number
If input passes validation, will return the input.
Throws an exception if passed in an invalid value. Infinity is accepted, but NaN is not.
'use strict'
const NumberModel = require('@eluvio/elv-js-helpers/Model/NumberModel')
NumberModel(42) //=> 42
NumberModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'
NumberModel(Infinity) //=> Infinity
NumberModel(-Infinity) //=> -Infinity
// Error message for NaN is not the greatest:
NumberModel(NaN) //=> EXCEPTION: 'expecting Number, got Number NaN'* → Number | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is:
If input passes validations, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const NumZeroToOneModel = require('@eluvio/elv-js-helpers/Model/NumZeroToOneModel')
NumZeroToOneModel(0) //=> 0
NumZeroToOneModel(0.5) //=> 0.5
NumZeroToOneModel(1) //=> 1
NumZeroToOneModel(42) //=> EXCEPTION: 'Value must be >= 0 and <= 1 (got: 42)'
NumZeroToOneModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'* → Number | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is:
If input passes validations, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const NumZeroToOneXModel = require('@eluvio/elv-js-helpers/Model/NumZeroToOneXModel')
NumZeroToOneXModel(0) //=> 0
NumZeroToOneXModel(0.5) //=> 0.5
NumZeroToOneXModel(1) //=> EXCEPTION: 'Value must be >= 0 and < 1 (got: 1)'
NumZeroToOneXModel(42) //=> EXCEPTION: 'Value must be >= 0 and < 1 (got: 42)'
NumZeroToOneXModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'Model → Object → String | undefinedkeyModelThe Model to check keys against
undefined otherwiseIterates over object properties and returns first property name (key) where passesModelCheck(keyModel) returns false
Returns undefined if all keys are valid.
'use strict'
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
const objBadKey = require('@eluvio/elv-js-helpers/Validation/objBadKey')
objBadKey(NonBlankStrModel, {foo:3}) //=> undefined
objBadKey(NonBlankStrModel, {' ':3}) //=> ' '
// function is curried: call with fewer params to obtain a narrower function
const findBlankKey = objBadKey(NonBlankStrModel)
findBlankKey({foo:3}) //=> undefined
findBlankKey({' ':3}) //=> ' 'Model → Object → [k, v] | undefinedvalueModelThe Model to check values against
Iterates over object values and returns 2-element array [key, value] pair for first value found that does not validate against Model
Returns undefined if all values are valid.
'use strict'
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
const objBadVal = require('@eluvio/elv-js-helpers/Validation/objBadVal')
objBadVal(NonBlankStrModel, {foo: 'bar'}) //=> undefined
objBadVal(NonBlankStrModel, {foo: ' '}) //=> ['foo', ' ']
objBadVal(NonBlankStrModel, {foo: 42}) //=> ['foo', 42]
// function is curried: call with fewer params to obtain a narrower function
const findBlankVal = objBadVal(NonBlankStrModel)
findBlankVal({foo: 'bar'}) //=> undefined
findBlankVal({foo: ' '}) //=> ['foo', ' ']* → Object | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is a Javascript Object
If input passes validation, will return the input.
Throws an exception if passed in an invalid value.
'use strict'
const ObjectModel = require('@eluvio/elv-js-helpers/Model/ObjectModel')
ObjectModel({foo: "bar"}) //=> {foo: "bar"}
ObjectModel('foo') //=> EXCEPTION: 'expecting Object, got String "foo"'[[String *]] → ObjectarrArray of 2-element arrays each containing an attribute name and value
Javascript's built-in Object.fromEntries() function.
Creates an object from a list of key/value pairs.
Not to be confused with fromPairs(), which takes a Crocks List of Pairs.
See also fromPairs
'use strict'
const objFromEntries = require('@eluvio/elv-js-helpers/Conversion/objFromEntries')
const kvPairs = [['a', 1], ['b',[['c', 3],['d', 4]]]]
objFromEntries(kvPairs) //=> { a: 1, b: [['c', 3],['d', 4]] }String → a → BooleankeyThe key to check for
xThe value to test
Returns true if item is an object with the specified key.
Returns false otherwise
'use strict'
const objHasKey = require('@eluvio/elv-js-helpers/Boolean/objHasKey')
objHasKey('foo', {foo: 'bar'}) //=> true
objHasKey('bar', {foo: 'bar'}) //=> false
objHasKey('foo', [1, 2, 3]) //=> false
objHasKey('1', {1: 42}) //=> true
objHasKey(1, {1: 42}) //=> false
// function is curried, pass less than full number of arguments to obtain another narrower function
const hasFoo = objHasKey('foo')
hasFoo({foo: 'bar'}) //=> true
hasFoo({bar: 'baz'}) //=> falseObject → [[String *]]objObject to convert
Array of 2-element arrays each containing an attribute name and value
Javascript's built-in Object.toEntries() function.
Creates an array of key/value pairs from an object.
Not to be confused with toPairs(), which returns a Crocks List of Pairs.
Provided for use in function composition.
See also toPairs
'use strict'
const objToEntries = require('@eluvio/elv-js-helpers/Conversion/objToEntries')
const obj = {a: 1, b: {c: 3, d:4}}
objToEntries(obj) //=> [['a', 1], ['b', {c: 3, d:4}]]a → Ok a(unnamed)The value to wrap in an Ok
Passthrough for the Ok variety of the Result Crocks Algebraic Data Type
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/crocks/Result.html for more details.
Allows users of elv-js-helpers to create Ok objects without adding the Crocks
package as a dependency.
There are 2 kinds of Result objects, Ok and Err, that wrap successful and failed computations, respectively.
Result objects are useful for handling errors in Functional pipelines and can collect multiple errors from various
branches of a workflow.
Normally, one does not create generic Result object instances, but rather Ok or Err instances.
'use strict'
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
Ok(42).inspect() //=> 'Ok 42'[ String ] → Object → Object(unnamed)A list of keys to omit
(unnamed)An object to process
A shallow copy of object with specified keys removed (as well as any keys pointing to undefined)
Passthrough for the omit() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Takes an array of strings and an object and returns a shallow copy of object with matching keys removed, as well
as any keys pointing to undefined.
'use strict'
const omit = require('@eluvio/elv-js-helpers/Functional/omit')
const myObject = {foo: "f", bar: "b"}
omit(['foo'], myObject) //=> {bar: 'b'}(a → Boolean | Pred a) → (a → Boolean | Pred a) → a → Boolean(unnamed)First function that returns a Boolean
(unnamed)Second function that returns a Boolean
Function which takes input, passes to both input functions, and then combines return values with logical OR
Passthrough for the or() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Given two predicate functions (a -> Boolean), returns a function that combines the two using logical OR.
'use strict'
const or = require('@eluvio/elv-js-helpers/Functional/or')
const isEven = x => (x % 2) === 0
const isNegative = x => x < 0
const isNegOrEven = or(isEven, isNegative)
isNegOrEven(3) //=> false
isNegOrEven(2) //=> true
isNegOrEven(-3) //=> true(a, b) → Pair a b(unnamed)The first (left) value to wrap in a Pair
(unnamed)The second (right) value to wrap in a Pair
Passthrough for the Pair Crocks Algebraic Data Type
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/crocks/Pair.html for more details.
Allows users of elv-js-helpers to create Pair objects without adding the Crocks
package as a dependency.
Pair objects are useful for creating Functional pipelines where an original value and a derived value both need to
be carried forward. They can also be useful for manipulating key-value pairs, or any situation where a value needs
an accompanying tag.
'use strict'
const Pair = require('@eluvio/elv-js-helpers/ADT/Pair')
const p = Pair(1,2)
p.inspect() //=> 'Pair( 1, 2 )'
p.fst() //=> 1
p.snd() //=> 2
Pair(42) //=> EXCEPTION: 'Pair: Must provide a first and second value'String → DateutcStringThe UTC timestamp to convert
Converts a string in UTC format (e.g. '2022-01-01T14:00:00Z' or '2022-01-01T14:00:00.0000Z') to a Javascript Date
Returns a NaN date if string is an invalid date or is not in format: YYYY-MM-DDThh:mm:ss[.s...]Z
Use utcStrToDate or UTCStrModel instead to generate an error on invalid date strings.
See also utcStrToDate
'use strict'
const dateObject = parseUTCStr('2022-01-01T14:00:00Z')
dateObject.valueOf() //=> 1641045600000
const dateObjectMilliseconds = parseUTCStr('2022-01-01T14:00:00.123Z')
dateObjectMilliseconds.valueOf() //=> 1641045600123
// Strings containing bad datetime return Date object containing NaN
const badDate = parseUTCStr('2022-99-01T14:00:00Z')
badDate.valueOf() //=> NaN
// Non-strings return Date object containing NaN
const nonStringDate = parseUTCStr(42)
nonStringDate.valueOf() //=> NaNModel → * → BooleanModelThe Model to test against
inputThe value to test
Returns true if the specified Model successfully validates an input, false otherwise.
Used when the caller does not care about the details of why the input failed validation.
'use strict'
const passesModelCheck = require('@eluvio/elv-js-helpers/Boolean/passesModelCheck')
const PositiveIntModel = require('@eluvio/elv-js-helpers/Model/PositiveIntModel')
passesModelCheck(PositiveIntModel, -1) //=> false
// function is curried: call with just first param to obtain a narrower function
const isPositiveInt = passesModelCheck(PositiveIntModel)
isPositiveInt(1) //=> true
isPositiveInt(0) //=> false
isPositiveInt('foo') //=> falseModel → * → BooleankeyModelthe Model to check keys against
objThe item to check
Returns
true if the input is an object and all the object's keys are valid instances of the specified Model OR the input is not a Javascript objectfalse if the input IS a Javascript object AND has a key (property name) that violates specified ModelIntended for use in an ObjectModel assertion.
Note that true is returned for non-object inputs.
If called with fewer than 2 arguments, will return a partially applied function
'use strict'
const passesObjKeyCheck = require('@eluvio/elv-js-helpers/Boolean/passesObjKeyCheck')
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
passesObjKeyCheck(NonBlankStrModel, {' ': 42}) //=> false
passesObjKeyCheck(NonBlankStrModel, {foo: 42}) //=> true
// test input not an object, check skipped:
passesObjKeyCheck(NonBlankStrModel, 3) //=> true
// function is curried: call with fewer params to obtain a narrower function
const hasNoBlankKeys = passesObjKeyCheck(NonBlankStrModel)
hasNoBlankKeys({' ': 42}) //=> false
hasNoBlankKeys({foo: 42}) //=> true
// test input not an object, check skipped:
hasNoBlankKeys(3) //=> trueModel → * → BooleanvalueModelthe Model to check values against
objThe item to check
Returns
true if the input is an object and all the object's values are valid instances of the specified Model OR the input is not a Javascript objectfalse if the input IS a Javascript object AND has a value that violates specified ModelIntended for use in an ObjectModel assertion.
Note that true is returned for non-object inputs.
If called with fewer than 2 arguments, will return a partially applied function
'use strict'
const passesObjValCheck = require('@eluvio/elv-js-helpers/Boolean/passesObjValCheck')
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
passesObjValCheck(NonBlankStrModel, {foo: ' '}) //=> false
passesObjValCheck(NonBlankStrModel, {foo: 'bar'}) //=> true
// value not a non-blank string:
passesObjValCheck(NonBlankStrModel, {foo: 42}) //=> false
// test input not an object, check skipped:
passesObjValCheck(NonBlankStrModel, 3) //=> true
// function is curried: call with fewer params to obtain a narrower function
const allValsNonBlankString = passesObjValCheck(NonBlankStrModel)
allValsNonBlankString({foo: ' '}) //=> false
allValsNonBlankString({foo: 'bar'}) //=> true
// value not a non-blank string:
allValsNonBlankString({foo: 42}) //=> false
// test input not an object, check skipped:
allValsNonBlankString(3) //=> true[String] → Object → Object(unnamed)A list of keys to include
(unnamed)The object to copy from
A shallow copy of the original object with only the specified keys
Passthrough for the pick() Crocks helper function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Not to be confused with the pick function from Ramda, although functionality is similar.
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Accepts a list of keys and an object then returns a partial shallow copy of the object with only the specified keys.
'use strict'
const pick = require('@eluvio/elv-js-helpers/Functional/pick')
const person = {
firstName: 'Arthur',
middleName: 'Philip',
lastName: 'Dent',
species: 'Human'
}
pick(['firstName', 'lastName'], person) //=> {firstName: 'Arthur', lastName: 'Dent'}
// function is curried, call with just first param to return a narrower function:
const speciesPicker = pick(['species'])
speciesPicker(person) //=> {species: 'Human'}((v, k) → Boolean) → {k: v} → {k: v}testFnfunction that accepts two args (value, key) and returns true or false
objarray of arrays or objects to pluck property or element from
Object containing only the keys where testFn(value, key) returned true
Passthrough for Ramda's pickBy function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns a new object with the keys selected by a test function called with value/key pairs.
'use strict'
const pickBy = require('@eluvio/elv-js-helpers/Functional/pickBy')
const valueIsEven = (v, k) => v % 2 === 0
const obj = {a: 1, b: 2, c: 3, d:4}
pickBy(valueIsEven, obj) //=> {b:2, d:4}
// function is curried: call with just first param to obtain a more specialized function
const evenValuesOnly = pickBy(valueIsEven)
evenValuesOnly(obj) //=> {b:2, d:4}((a → b), …, (y → z)) → a → z(unnamed)Two or more curried functions to compose in left-to-right order
The composed function
Passthrough for the pipe() Crocks helper function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/functions/helpers.html#pipe for more details.
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Composes functions in left to right order (which is generally more readable than the right-to-left order used by
compose) and returns a new function.
'use strict'
const pipe = require('@eluvio/elv-js-helpers/Functional/pipe')
// function has only one input, no need to curry
const trim = str => str.trim()
// function has only one input, not need to curry
const capitalizeFirst = str => str.charAt(0).toUpperCase() + str.slice(1)
const trimAndCapitalize = pipe(trim, capitalizeFirst)
trimAndCapitalize(' foo ') //=> 'Foo'Chain m => ((a → m b), …, (y → m z)) → a → m z(unnamed)Two or more chainable operations
A chainable ADT
Renamed and modified version of the pipeK() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Allows composing functional workflows that would normally require use of .chain().
'use strict'
const pipeChainable = require('@eluvio/elv-js-helpers/Functional/pipeChainable')
// https://api.dictionaryapi.dev/api/v2/entries/en/aardvark
// https://oeis.org/search?q=id:A000040&fmt=jsonNumber | String → List → [*] | EXCEPTIONpropOrIndexthe property or array element index to pull from each item in list
xarray of arrays or objects to pluck property or element from
List with the specified property or array element from each element in x
Passthrough for Ramda's pluck function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns a new list by plucking the same named property (or array element) off all objects in the list supplied.
If an item does not have the specified property or array index, result will contain undefined for that element.
Will return [undefined] if second argument is something other than a list or undefined.
Will throw an exception if undefined is passed in for second argument.
'use strict'
const pluck = require('@eluvio/elv-js-helpers/Functional/pluck')
const arrOfObj = [{a: 1, b:2}, {b:2, c:3}]
pluck('b', arrOfObj) //=> [2, 2]
pluck('a', arrOfObj) //=> [1, undefined]
const arrOfArr = [['a', 'b'], ['b', 'c', 'd']]
pluck(1, arrOfArr) //=> ['b', 'c']
pluck(2, arrOfArr) //=> [undefined, 'd']
pluck(3, 3) //=> [undefined]
pluck(3, undefined) //=> EXCEPTION: 'Cannot read properties of undefined'
// function is curried: call with just first param to obtain a more specialized function
const getFirstElements = pluck(0)
getFirstElements(arrOfArr) //=> ['a', 'b']* → * | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is:
If input passes validations, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const PositiveFracStrModel = require('@eluvio/elv-js-helpers/Model/PositiveFracStrModel')
PositiveFracStrModel('42') //=> '42'
PositiveFracStrModel('0') //=> EXCEPTION: 'Value must be > 0 (got: "0")'
PositiveFracStrModel('42/2') //=> '42/2'
PositiveFracStrModel('foo') //=> EXCEPTION: 'Value must be a string in the form of a whole number or a fraction (got: "foo")'* → * | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is:
If input passes validations, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const PositiveIntModel = require('@eluvio/elv-js-helpers/Model/PositiveIntModel')
PositiveIntModel(42) //=> 42
PositiveIntModel(0) //=> EXCEPTION: 'Value must be > 0 (got: 0)'
PositiveIntModel(4.2) //=> EXCEPTION: 'Value must be an integer (got: 4.2)'
PositiveIntModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'
PositiveIntModel(Infinity) //=> EXCEPTION: 'Value must be an integer (got: Infinity)'
PositiveIntModel(-Infinity) //=> EXCEPTION: 'Value must be an integer (got: -Infinity)'* → * | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is:
If input passes validations, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const PositiveNumModel = require('@eluvio/elv-js-helpers/Model/PositiveNumModel')
PositiveNumModel(42) //=> 42
PositiveNumModel(0) //=> EXCEPTION: 'Value must be > 0 (got: 0)'
PositiveNumModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'
PositiveNumModel(Infinity) //=> Infinity
PositiveNumModel(-Infinity) //=> EXCEPTION: 'Value must be > 0 (got: -Infinity)'(a, [b], c) → avalueThe value to redact
addlPatternsAny additional patters to test keys against
parentKeythe key that value was stored under, if any
Redacts string values within objects. Used to filter data before logging.
If passed an object or array, will recursively traverse it and construct a copy where object string values stored under certain keys are replaced with redacted versions.
If an object key is associated with a value that is a string, the key is tested against an array of regular expressions (REDACT_PATTERNS, plus any additional patterns passed in). If any match, then the string will be replaced with a redacted version:
If passed anything other than an object or array, will return the original value.
'use strict'
const redact = require('@eluvio/elv-js-helpers/Conversion/redact')
const data = {
user: 'foo',
password: 'my very long password',
key: '1234'
}
const redacted = JSON.stringify(redact(data))
console.log(redacted) //=> OUTPUT: '{"user":"foo","password":"[REDACTED ...word]","key":"[REDACTED]"}'
const arr = [
{password: 'x'},
{PRIVATE_KEY: '1234'},
{foo: 'bar'}
]
const redactedArr = JSON.stringify(redact(arr))
console.log(redactedArr) //=> OUTPUT: '[{"password":"[REDACTED]"},{"PRIVATE_KEY":"[REDACTED]"},{"foo":"bar"}]'Type:Array.<RegExp>"[{},{},{},{},{},{},{},{},{},{},{}]"
Array of Regular Expressions
used by redact() to decide whether a particular object attribute should have its value redacted.
'use strict'
const REDACT_PATTERNS = require('@eluvio/elv-js-helpers/Conversion/REDACT_PATTERNS')
const shouldRedact = x => REDACT_PATTERNS.find(pattern => pattern.test(x)) !== undefined;
shouldRedact('Password') //=> true
shouldRedact('My_secret') //=> true
shouldRedact('foo') //=> false((a, b) → a) → a → [b] → a(unnamed)the iterator function, accepting an accumulator (a) and the current list element (b) and returning an updated value for accumulator
(unnamed)initial value for accumulator
final value of accumulator
Passthrough for Ramda's reduce function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns a value created by iterating through a list with an accumulator and a function, successively calling the function with the updated accumulator and next element as the arguments.
'use strict'
const reduce = require('@eluvio/elv-js-helpers/Functional/reduce')
const arrOfInt = [1, 2, 3, 4, 5]
const add = (a,b) => a+b
const mult = (a,b) => a*b
reduce(add, 0, arrOfInt) //=> 15
reduce(mult, 1, arrOfInt) //=> 120
// note that choosing proper initial value for accumulator is important!
reduce(mult, 0, arrOfInt) //=> 0
const append = (a,b) => a.concat([b])
reduce(append, [], arrOfInt) //=> [1, 2, 3, 4, 5][string], …stringsAndOrRegExps → RegExp | EXCEPTIONJavascript tagged template function to allow composing regular expressions.
Throws an exception if all sub-regexes do not have the same flags.
'use strict'
const reFromTemplate = require('@eluvio/elv-js-helpers/Conversion/reFromTemplate')
const RE_LETTER = /[a-zA-Z]/
const RE_DIGIT = /[0-9]/
const RE_UNICODE_LETTER = /\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}/u
const RE_UNICODE_DIGIT = /\p{Nd}/u
const RE_LETTER_DIGIT = reFromTemplate`${RE_LETTER}${RE_DIGIT}`
const RE_UNICODE_LETTER_DIGIT = reFromTemplate`${RE_UNICODE_LETTER}${RE_UNICODE_DIGIT}`
RE_LETTER_DIGIT.source //=> '(?:[a-zA-Z])(?:[0-9])'
RE_LETTER_DIGIT.flags //=> ''
RE_UNICODE_LETTER_DIGIT.source //=> '(?:\\p{Lu}|\\p{Ll}|\\p{Lt}|\\p{Lm}|\\p{Lo})(?:\\p{Nd})'
RE_UNICODE_LETTER_DIGIT.flags //=> 'u'
reFromTemplate`${RE_DIGIT}${RE_UNICODE_LETTER}` //=> EXCEPTION: 'All interpolated regular expressions must have the same flags (found: ["","u"])'
RE_LETTER_DIGIT.test('a4') //=> true
RE_LETTER_DIGIT.test('4a') //=> false
RE_LETTER_DIGIT.test('Å𝟜') //=> false
RE_LETTER_DIGIT.test('𝟜Å') //=> false
RE_UNICODE_LETTER_DIGIT.test('a4') //=> true
RE_UNICODE_LETTER_DIGIT.test('4a') //=> false
RE_UNICODE_LETTER_DIGIT.test('Å𝟜') //=> true
RE_UNICODE_LETTER_DIGIT.test('𝟜Å') //=> false
// strings are interpolated as literal match
const FOO_STR = 'foo'
const BAR_STR = 'bar'
const RE_FOOBAR = reFromTemplate`^${FOO_STR}${BAR_STR}$`
RE_FOOBAR.test('foobar') //=> true
RE_FOOBAR.test('foobarbar') //=> false
RE_FOOBAR.test('FOOBAR') //=> false
// if sub-regexps have start/end matchers, it can result in regexps that never match
const RE_FOO_ONLY = /^foo$/
const RE_BAR_ONLY = /^bar$/
const RE_FOOBAR_ONLY = reFromTemplate`^${RE_FOO_ONLY}${RE_BAR_ONLY}$`
RE_FOOBAR_ONLY.test('foobar') //=> false
RE_FOOBAR_ONLY.test('foobarbar') //=> false
RE_FOOBAR_ONLY.test('FOOBAR') //=> falseResult [e] a → ObjectresultThe Crocks Result instance to convert
Converts a Crocks Result to a Plain Old Javascript Object.
If the Result is an Ok, returns {ok: true, value: a}, where a is the value wrapped by the Ok
If the Result is an Err, returns {ok: false, errMsgs: uniqErrStringArray, errors: arrayErrVal}
where errors is the array value wrapped by the Err (often an array of Javascript Error objects), and errMsgs
is the result of passing each item in that array to String() then removing duplicates.
Throws an error if the Result is an Err that does not contain an array. (This situation is not usually encountered,
as the Err() function performs automatic conversion to single-element array if the input is not an array)
'use strict'
const resultToPOJO = require('@eluvio/elv-js-helpers/Conversion/resultToPOJO')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
const dumpJSON = require('@eluvio/elv-js-helpers/Misc/dumpJSON')
resultToPOJO(Ok(42)) //=> {ok: true, value: 42}
resultToPOJO(Err(['query invalid'])) //=> {ok: false, errMsgs: ["query invalid"], errors: ["query invalid"]}
const e = RangeError('value too large')
dumpJSON(resultToPOJO(Err([e]))) //=> OUTPUT: `{
// "ok": false,
// "errMsgs": [
// "RangeError: value too large"
// ],
// "errors": [
// {}
// ]
// }`Result e a → e | axThe Crocks Result instance to unwrap
Returns the value wrapped by a Crocks Result, whether it is an Ok or an Err
Throws an exception if not passed a Result.
See also resultToPOJO
'use strict'
const resultUnwrap = require('@eluvio/elv-js-helpers/Conversion/resultUnwrap')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
resultUnwrap(Err(['invalid query'])) //=> ['invalid query']
resultUnwrap(Ok(42)) //=> 42a :: String | Array => a → axthe item to reverse
Reversed string or array
Passthrough for Ramda's reverse function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns a new list or string with the elements or characters in reverse order.
'use strict'
const reverse = require('@eluvio/elv-js-helpers/Functional/reverse')
reverse([1, 2, 3]) //=> [3, 2, 1]
reverse("abc") //=> "cba"Type:RegExp{}
RegExp used for validation of a Base58 character.
NOTE: This RegExp will match a string that contains a Base58 character anywhere within. It is intended for use in more complex RegExps created with reFromTemplate()
'use strict'
const RE_BASE58_CHAR = require('@eluvio/elv-js-helpers/Validation/RE_BASE58_CHAR')
RE_BASE58_CHAR.test('1') //=> true
RE_BASE58_CHAR.test('l') //=> false
RE_BASE58_CHAR.test('l1l') //=> true
const reFromTemplate = require('@eluvio/elv-js-helpers/Conversion/reFromTemplate')
const RE_SINGLE_BASE58_CHAR = reFromTemplate`^${RE_BASE58_CHAR}$`
RE_SINGLE_BASE58_CHAR.test('1') //=> true
RE_SINGLE_BASE58_CHAR.test('l') //=> false
RE_SINGLE_BASE58_CHAR.test('l1l') //=> falseType:RegExp{}
RegExp used for validation of rational numbers expressed as strings of form x, -x, x/y, or -x/y, where x and y are integers and y !== 0.
Leading zeroes are allowed.
Capture groups parse the string into separate matches for numerator and slash+denominator.
'use strict'
const RE_RATIONAL = require('@eluvio/elv-js-helpers/Validation/RE_RATIONAL')
RE_RATIONAL.test('0') //=> true
RE_RATIONAL.test('-0') //=> true
RE_RATIONAL.test('0/1') //=> true
RE_RATIONAL.test('0/010') //=> true
RE_RATIONAL.test('1/0') //=> false
RE_RATIONAL.test('-0') //=> true
RE_RATIONAL.test('3.14') //=> false
RE_RATIONAL.test('9 1/2') //=> false
RE_RATIONAL.test('19/2') //=> true
RE_RATIONAL.test('007') //=> true
const fracString = '22/7'
const match = fracString.match(RE_RATIONAL)
if (!match) throw Error('Rational number string not in proper format')
// first capture group is numerator:
match[1] //=> '22'
// second capture group is slash + denominator:
match[2] //=> '/7'Type:RegExp{}
RegExp used for first-pass validation of UTC timestamp of form YYYY-MM-DDThh:mm:ssZ, e.g. '2022-01-01T14:00:00Z'.
Capture groups parse the string into separate matches for year/month/day/hour/minute/second.
'use strict'
const RE_UTC_TIMESTAMP = require('@eluvio/elv-js-helpers/Datetime/RE_UTC_TIMESTAMP')
RE_UTC_TIMESTAMP.test('2022-01-02T03:45:00Z') //=> true
RE_UTC_TIMESTAMP.test('foo') //=> false
const utcString = '2022-01-02T03:45:00Z'
const match = utcString.match(RE_UTC_TIMESTAMP)
if (!match) throw Error('UTC timestamp not in proper format')
// year
parseInt(match[1], 10) //=> 2022
// month
parseInt(match[2], 10) //=> 1
// day
parseInt(match[3], 10) //=> 2
// hour
parseInt(match[4], 10) //=> 3
// minute
parseInt(match[5], 10) //=> 45
// second
parseInt(match[6], 10) //=> 0
const utcStringFrac = '2022-01-02T03:45:00.123Z'
const fracMatch = utcStringFrac.match(RE_UTC_TIMESTAMP)
// fractional seconds
parseFloat(fracMatch[7]) //=> 0.123Type:RegExp{}
RegExp used for validation of UUID strings in format '00000000-0000-0000-0000-000000000000'
Both upper case and lower case are accepted for hex digits.
'use strict'
const RE_UUID = require('@eluvio/elv-js-helpers/Validation/RE_UUID')
RE_UUID.test('0') //=> false
RE_UUID.test('ABCDEF00-0000-0000-0000-000000000000') //=> true
RE_UUID.test('abcdef00-0000-0000-0000-000000000000') //=> true
RE_UUID.test('abcdef00-0000-0000-0000-ABCDEF000000') //=> trueType:RegExp{}
RegExp used for validation of UUID strings in format '00000000-0000-0000-0000-000000000000' using only lower case letters for hex digits
(Note that this is non-standard, RFC4122 specifies that both upper and lower case letters are acceptable)
'use strict'
const RE_UUID_LOWER_CASE = require('@eluvio/elv-js-helpers/Validation/RE_UUID_LOWER_CASE')
RE_UUID_LOWER_CASE.test('0') //=> false
RE_UUID_LOWER_CASE.test('ABCDEF00-0000-0000-0000-000000000000') //=> false
RE_UUID_LOWER_CASE.test('abcdef00-0000-0000-0000-000000000000') //=> true
RE_UUID_LOWER_CASE.test('abcdef00-0000-0000-0000-ABCDEF000000') //=> falseType:RegExp{}
RegExp used for validation of UUID strings in format '00000000-0000-0000-0000-000000000000' using only upper case letters for hex digits
(Note that this is non-standard, RFC4122 specifies that both upper and lower case letters are acceptable)
'use strict'
const RE_UUID_UPPER_CASE = require('@eluvio/elv-js-helpers/Validation/RE_UUID_UPPER_CASE')
RE_UUID_UPPER_CASE.test('0') //=> false
RE_UUID_UPPER_CASE.test('ABCDEF00-0000-0000-0000-000000000000') //=> true
RE_UUID_UPPER_CASE.test('abcdef00-0000-0000-0000-000000000000') //=> false
RE_UUID_UPPER_CASE.test('abcdef00-0000-0000-0000-ABCDEF000000') //=> falsea → Boolean → ((a, a) → Integer) → a → BooleanlowerBoundthe lower bound to be satisfied
upperBoundthe upper bound to be satisfied
lowerInclusiveif true, then value is allowed equal lowerBound
upperInclusiveif true, then value is allowed equal upperBound
comparatorFnThe function to be used to compare value with lowerBound and upperBound.
Must accept two values and return -1 if first value is less than the second,
1 if the second value is less than the first, and zero otherwise.
valueThe item to check against lowerBound and upperBound
Returns true if value satisfies specified bounds, false otherwise
Note that this function performs no type checking and relies on comparatorFn to determine if input satisfies bounds.
If called with fewer than 6 arguments, will return a partially applied function
'use strict'
const satisfiesBetweenBounds = require('@eluvio/elv-js-helpers/Boolean/satisfiesBetweenBounds')
const compare = require('@eluvio/elv-js-helpers/Functional/compare')
satisfiesBetweenBounds(0, 42, true, true, compare, 42) //=> true
satisfiesBetweenBounds(0, 42, true, true, compare, 0) //=> true
satisfiesBetweenBounds(0, 42, true, true, compare, -1) //=> false
satisfiesBetweenBounds(0, 42, false, false, compare, 0) //=> false
// function is curried: call with fewer params to obtain a narrower function
const isFromZeroToOne = satisfiesBetweenBounds(0, 1, true, true, compare)
isFromZeroToOne(0.5) //=> true
isFromZeroToOne(1) //=> true
isFromZeroToOne(1.5) //=> falsea → Boolean → ((a, a) → Integer) → a → BooleanlowerBoundthe lower bound to be satisfied
inclusiveif true, then value is allowed equal lowerBound
comparatorFnThe function to be used to compare value and lowerBound.
Must accept two values and return -1 if first value is less than the second,
1 if the second value is less than the first, and zero otherwise.
valueThe item to check against lowerBound
Returns true if value satisfies specified bound, false otherwise
Note that this function performs no type checking and relies on comparatorFn to determine if input satisfies bound.
If called with fewer than 4 arguments, will return a partially applied function
'use strict'
const satisfiesLowerBound = require('@eluvio/elv-js-helpers/Boolean/satisfiesLowerBound')
const compare = require('@eluvio/elv-js-helpers/Functional/compare')
satisfiesLowerBound(0, true, compare, 42) //=> true
satisfiesLowerBound(0, true, compare, 0) //=> true
satisfiesLowerBound(0, true, compare, -1) //=> false
satisfiesLowerBound(0, false, compare, 0) //=> false
// function is curried: call with fewer params to obtain a narrower function
const isPositive = satisfiesLowerBound(0, false, compare)
isPositive(-1) //=> false
isPositive(0) //=> false
isPositive(1) //=> truea → Boolean → ((a, a) → Integer) → a → BooleanupperBoundthe upper bound to be satisfied
inclusiveif true, then value is allowed equal upperBound
comparatorFnThe function to be used to compare value and upperBound.
Must accept two values and return -1 if first value is less than the second,
1 if the second value is less than the first, and zero otherwise.
valueThe item to check against upperBound
Returns true if value satisfies specified bound, false otherwise
Note that this function performs no type checking and relies on comparatorFn to determine if input satisfies bound.
If called with fewer than 4 arguments, will return a partially applied function
'use strict'
const satisfiesUpperBound = require('@eluvio/elv-js-helpers/Boolean/satisfiesUpperBound')
const compare = require('@eluvio/elv-js-helpers/Functional/compare')
satisfiesUpperBound(42, true, compare, 42) //=> true
satisfiesUpperBound(42, true, compare, 0) //=> true
satisfiesUpperBound(42, true, compare, -1) //=> true
satisfiesUpperBound(42, false, compare, 42) //=> false
// function is curried: call with fewer params to obtain a narrower function
const isNegative = satisfiesUpperBound(0, false, compare)
isNegative(-1) //=> true
isNegative(0) //=> false
isNegative(1) //=> falseNumber → ((*) → a) → (*) → a(unnamed)arity - Number of arguments for the returned function to accept
(unnamed)The function to convert
Curried version of function with fixed argument count
Renamed passthrough for the nAry() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Converts a function that takes a variable number of arguments and converts to a curried function that one that specified number of arguments.
'use strict'
const setArity = require('@eluvio/elv-js-helpers/Functional/setArity')
const maxOfThree = setArity(3, Math.max)
// creates partially applied function with 1 argument applied (waiting for 2 more):
const maxNeedTwoMore = maxOfThree(42)
// creates partially applied function with 2 arguments applied (waiting for 1 more):
const maxNeedOneMore = maxNeedTwoMore(0)
maxNeedOneMore(-42) //=> 42Idx = String | Int | Symbol => [Idx] → * → Object → ObjectpathArraythe path to set, expressed as an array
valuethe value to store at path
objectthe original object
Shallow copy of object with
Renamed passthrough for Ramda's assocPath function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns a shallow clone of object with value set at specified path. Any missing or non-object keys in path will be overridden. WARNING: arrays along the path will be converted into objects with numeric strings as keys (see examples)
Unlike getPath, does not support negative numbers as indexes to set element counting from end of array. Ramda
will actually end up adding a property to the array using string of negative number as the key. This function
will throw an error instead.
For safety, you should clone the original object before passing into setPath.
'use strict'
const setPath = require('@eluvio/elv-js-helpers/Functional/setPath')
const clone = require('@eluvio/elv-js-helpers/Functional/clone')
const myObject = {foo: {bar: [1, 2, 3]}}
setPath(['foo'], 42, clone(myObject)) //=> {foo: 42}
setPath(['bar'], 42, clone(myObject)) //=> {bar: 42, foo: {bar: [1, 2, 3]}}
// numeric values interpreted as array indexes
setPath(['foo', 'bar', 0], 42, clone(myObject)) //=> {foo: {bar: [42, 2, 3]}}
// empty values inserted into existing arrays if needed
setPath(['foo', 'bar', 5], 42, clone(myObject)) //=> {foo: {bar: [1, 2, 3, , , 42]}}
// WARNING: using a string expressing a number when an array exists at path causes other array elements to be
// converted to key:value pairs
setPath(['foo', 'bar', '0'], 42, clone(myObject)) //=> {foo: {bar: {0: 42, 1: 2, 2: 3}}}
setPath(['foo', 'bar', 'baz'], 42, clone(myObject)) //=> {foo: {bar: {0: 1, 1: 2, 2: 3, baz: 42}}}
// empty values inserted into new arrays if needed
setPath(['foo', 'bar', 'baz', 5], 42, clone(myObject)) //=> {foo: {bar: {0: 1, 1: 2, 2: 3, baz: [ , , , , , 42]}}}
// negative numbers NOT supported as array indexes
setPath(['foo', 'bar', -1], 42, clone(myObject)) //=> EXCEPTION: "expecting Array[2] to be String or NonNegativeInteger, got Number -1"Ord b => (a → b) → [a] → [a](unnamed)the function to obtain the sort key for each element
(unnamed)the list to sort
Passthrough for Ramda's sortBy function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Sorts a list according the result of calling a function on each element of the list.
'use strict'
const sortBy = require('@eluvio/elv-js-helpers/Functional/sortBy')
const sortByName = sortBy(x => x.name)
const sortByNameCaseInsensitive = sortBy(x => x.name.toLowerCase())
sortByName([
{name: "alpha"},
{name: "Bravo"},
{name: "charlie"}
]).map(x => x.name) //=> ['Bravo', 'alpha', 'charlie']
sortByNameCaseInsensitive([
{name: "alpha"},
{name: "Bravo"},
{name: "charlie"}
]).map(x => x.name) //=> ['alpha', 'Bravo', 'charlie']* → String | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is a Javascript String
If input passes validation, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const StringModel = require('@eluvio/elv-js-helpers/Model/StringModel')
StringModel('foo') //=> 'foo'
StringModel(42) //=> EXCEPTION: 'expecting String, got Number 42'string → string → object → object | EXCEPTIONfieldName1The name of one field to swap
fieldName2The name of the other field to swap
objObject
Swaps values in two properties of an object.
Throws an exception if either fieldname is not found, or if obj is not an object
See also swapFieldsResult
'use strict'
const swapFields = require('@eluvio/elv-js-helpers/Functional/swapFields')
const obj = {foo: 1, bar: 2, baz: 3}
swapFields('foo', 'bar', obj) //=> {foo: 2,bar: 1,baz: 3}
swapFields('foo', 'qaz', obj) //=> EXCEPTION: "Property 'qaz' not found"
swapFields('foo', 'bar', null) //=> EXCEPTION: "expecting obj to be Object, got null"string → string → Result → ResultfieldName1The name of one field to swap
fieldName2The name of the other field to swap
objObject
Swaps values in two properties of an object.
Returns a Result Crocks Algebraic Data Type
(Copyright © 2016, Ian Hofmann-Hicks, ISC license) wrapping a new object. Note that new object is a shallow copy of the original.
If original object was an ObjectModel instance, will return wrapped plain javascript object with
model constraints removed.
If either fieldname is not found, or if obj is not an object, will return a Result of type Err.
See also swapFields
'use strict'
const swapFieldsResult = require('@eluvio/elv-js-helpers/Functional/swapFieldsResult')
const resultToPOJO = require('@eluvio/elv-js-helpers/Conversion/resultToPOJO')
const obj = {foo: 1, bar: 2, baz: 3}
const swappedObjResult = swapFieldsResult('foo', 'bar', obj)
resultToPOJO(swappedObjResult).ok //=> true
swappedObjResult.inspect() //=> 'Ok { foo: 2, bar: 1, baz: 3 }'
const errResult = swapFieldsResult('foo', 'bar', null)
resultToPOJO(errResult).ok //=> false
errResult.inspect() //=> 'Err [ "swapFields: expecting obj to be Object, got null" ]'() → StringReturns locale string from current environment (see http://www.lingoes.net/en/translator/langcode.htm)
The locale string is used to format dates and times
'use strict'
const sysLocale = require('@eluvio/elv-js-helpers/Datetime/sysLocale')
sysLocale() //=> 'en-US'() → StringReturns Datetime zone string from current environment
'use strict'
const sysTimezone = require('@eluvio/elv-js-helpers/Datetime/sysTimezone')
sysTimezone() //=> 'America/Los_Angeles'{} → atrue
Ignores input and always returns true.
Used for composing functional workflows, often indicating 'always'.
'use strict'
const T = require('@eluvio/elv-js-helpers/Functional/T')
T(42) //=> true
T() //=> true[*] → [*] | EXCEPTIONString → String(unnamed)an iterable list of elements
Array containing all but the first element, or String containing all but the first character
Passthrough for Ramda's tail function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns all but the first element of a list or string
'use strict'
const tail = require('@eluvio/elv-js-helpers/Functional/tail')
tail([1, 2, 3, 4, 5]) //=> [2, 3, 4, 5]
tail([1]) //=> []
tail([]) //=> []
tail('abc') //=> 'bc'
tail('a') //=> ''
tail('') //=> ''
// NOTE: bad data types are ignored
tail(0) //=> []
tail({foo: 'bar'}) //=> []
// undefined will produce an exception
tail(undefined) //=> EXCEPTION: 'Cannot read properties of undefined'String → THROWmessageError message for exception
Throws an exception. Used to allow terser code, e.g. replacing if/else with a ternary expression.
'use strict'
const throwError = require('@eluvio/elv-js-helpers/Misc/throwError')
throwError('clear and helpful error message') //=> EXCEPTION: 'clear and helpful error message'ObjectOrModel → * → undefined | THROWmodelOrObja Model or an Object that can be used as an ObjectModel spec
argsthe input to validate
Throws an exception with the calling function's name if args object does not validate successfully.
Meant to be used at the beginning of a function.
Usually the function accepts named parameters (i.e. an object) and the validation will be checking an object.
WARNING: must be called directly by the function in order to show calling function name correctly - do not pipe/compose.
'use strict'
const throwIfArgsBad = require('@eluvio/elv-js-helpers/Validation/throwIfArgsBad')
const defObjectModel = require('@eluvio/elv-js-helpers/ModelFactory/defObjectModel')
const NonNegativeIntModel = require('@eluvio/elv-js-helpers/Model/NonNegativeIntModel')
const PersonModel = defObjectModel('Person', {first: String, last: String, age: NonNegativeIntModel})
const getAge = person => {
throwIfArgsBad(PersonModel, person)
return person.age
}
const validPerson = {first: 'Arthur', last: 'Dent', age: 30}
getAge(validPerson) //=> 30
const badData = {first: 'Arthur', last: 'Dent'}
getAge(badData) //=> EXCEPTION: 'getAge() expecting age to be Number, got undefined'
getAge(42) //=> EXCEPTION: 'getAge() expecting Object, got Number 42'String → a → a | THROWmessagethe error message to use in the exception
valuethe value to check for falsiness
Throws an exception with the specified message if a falsy value is passed in. Otherwise returns the truthy value unchanged.
'use strict'
const throwIfFalse = require('@eluvio/elv-js-helpers/Validation/throwIfFalse')
const PASSWORD_REGEX_4 = /[A-Z]{4}/
const PASSWORD_REGEX_42 = /[A-Z]{42}/
const password = 'ABCD'
throwIfFalse('password must be 42 upper-case letters', PASSWORD_REGEX_42.test(password)) //=> EXCEPTION: 'password must be 42 upper-case letters'
throwIfFalse('password must be 4 upper-case letters', PASSWORD_REGEX_4.test(password)) //=> true
throwIfFalse('foo', 42) //=> 42
throwIfFalse('foo', []) //=> []String → a → a | THROWmessagethe error message to use in the exception
valuethe value to check for truthiness
Throws an exception with the specified message if a truthy value is passed in. Otherwise returns the falsy value unchanged.
'use strict'
const throwIfTrue = require('@eluvio/elv-js-helpers/Validation/throwIfTrue')
const x = 0
const y = 42
throwIfTrue('division by zero', x === 0) //=> EXCEPTION: "division by zero"
throwIfTrue('division by zero', y === 0) //=> false
throwIfTrue('foo', null) //=> null
throwIfTrue('foo', 0) //=> 0String → a → a | THROWmessagethe error message to use in the exception
valuethe value to check if undefined
Throws an exception with the specified message if undefined is passed in.
Otherwise returns the value unchanged.
'use strict'
const throwIfUndefined = require('@eluvio/elv-js-helpers/Validation/throwIfUndefined')
let u
const x = 0
let y = 42
throwIfUndefined('value is undefined', u) //=> EXCEPTION: "value is undefined"
throwIfUndefined('value is undefined', x) //=> 0
throwIfUndefined('value is undefined', y) //=> 42
throwIfUndefined('value is undefined')() //=> EXCEPTION: "value is undefined"a → BooleanfnThe function to test
Returns true if fn() throws an exception when called.
Returns false otherwise.
'use strict'
const throwsException = require('@eluvio/elv-js-helpers/Boolean/throwsException')
throwsException(() => Object().foo.bar) //=> true
throwsException(() => 42/42) //=> false
// returns `true` if passed something that cannot be called.
throwsException(0) //=> true(Number → a) → Number → [a]fnthe function to call with index
repeatCountthe number of times to call the function
List with result of function call(s)
Passthrough for Ramda's times function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns a list containing result of passing 0 based index to a function the specified number of times, incrementing index each time.
'use strict'
const times = require('@eluvio/elv-js-helpers/Functional/times')
const double = x => x * 2
times(double, 3) //=> [0, 2, 4]
// function is curried: call with just first param to obtain a more specialized function
const getSquares = times(x => x ** 2)
getSquares(4) //=> [0, 1, 4, 9](String | [String], Object) → (Date → String)localesThe locales argument to pass to Date.toLocaleString()
optionsThe options argument to pass to Date.toLocaleString()
Takes two inputs (for locales and options and returns a function that will accept a
Javascript Date
object and return a string obtained by invoking its toLocaleString() method with the
specified locales and options arguments.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString for more details.
See https://devhints.io/wip/intl-datetime for a list of options.
See https://gist.github.com/diogocapela/12c6617fc87607d11fd62d2a4f42b02a for a list of time zones.
'use strict'
const toLocaleString = require('@eluvio/elv-js-helpers/Datetime/toLocaleString')
const utcStrToDate = require('@eluvio/elv-js-helpers/Datetime/utcStrToDate')
const myDate = utcStrToDate('2022-03-01T14:00:00Z')
const USA_Pacific_short = toLocaleString(
'en-US',
{
hour: 'numeric',
day: 'numeric',
minute: 'numeric',
month: 'short',
second: 'numeric',
timeZone: 'America/Los_Angeles',
timeZoneName: 'short'
}
)
USA_Pacific_short(myDate) //=> 'Mar 1, 6:00:00 AM PST'
const UK_long = toLocaleString(
'en-GB',
{
dateStyle: 'full',
timeStyle: 'long',
timeZone: 'Europe/London'
}
)
UK_long(myDate) //=> 'Tuesday, 1 March 2022 at 14:00:00 GMT'
// function is curried, it is possible to pass all arguments at once to define and invoke in one step:
const options = {
dateStyle: 'short',
timeStyle: 'short',
timeZone: 'America/New_York'
}
toLocaleString('en-US', options, myDate) //=> '3/1/22, 9:00 AM'Object → List (Pair String a)(unnamed)The object to convert
List of Pairs
Passthrough for the toPairs() Crocks function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
See https://crocks.dev/docs/crocks/Pair.html#topairs for more details.
Converts an object into a Crocks List of Pair objects, each with key as first element and value as second element.
Not to be confused with Ramda's toPairs() function, which returns a 2-level regular Javascript array.
'use strict'
const toPairs = require('@eluvio/elv-js-helpers/Conversion/toPairs')
const kvPairs = toPairs({a:1, b:2})
kvPairs.inspect() //=> 'List [ Pair( "a", 1 ), Pair( "b", 2 ) ]'[*] → [Boolean] → *choiceArrayAn array of items to choose from
boolArrayAn array of booleans used to determine which element to return from choiceArray
Returns an item from an array of choices, making the choice based on a separate array of booleans.
Used to express multilevel if-then control flows in a more Functional style.
// Given the following table:
// | isChild | isMale | result |
// |---------|--------|---------|
// | F | F | 'woman' |
// | F | T | 'man' |
// | T | F | 'girl' |
// | T | T | 'boy' |
'use strict'
const truthTable = require('@eluvio/elv-js-helpers/Functional/truthTable')
let isChild = false
let isMale = false
truthTable(['woman','man','girl','boy'],[isChild, isMale]) //=> "woman"
// For comparison - expressed using if/then
if(isChild) {
if(isMale) {
return 'boy'
} else {
return 'girl'
}
} else {
if(isMale) {
return 'man'
} else {
return 'woman'
}
}((*) → b) → (*) → Result e bfnThe function to convert
Slightly modified version of the tryCatch() Crocks helper function
(Copyright © 2016, Ian Hofmann-Hicks, ISC license)
Modified to use elv-js-helper's version of Err(), which wraps non-array values into a single-element array.
See https://crocks.dev/docs/functions/helpers.html#trycatch for more details.
Allows users of elv-js-helpers to use the function without adding the Crocks
package as a dependency.
Converts the supplied function into one that returns an Ok if successful or an Err if it throws an error.
If the function is a method of a class instance you will need to suffix the function with .bind(your_instance_var)
(see example below)
else the method call will execute with this set incorrectly, leading to confusing errors.
Note that calling tryCatch with just a function will not execute the function immediately - instead it will return
another function that you can call with arguments.
To immediately invoke the function, use one of the following:
tryCatch(myFunction, arguments...)
tryCatch(myFunction)(arguments...)
If your function takes no arguments, you can use one of the following:
tryCatch(myFunction, undefined)
tryCatch(myFunction)()
'use strict'
const tryCatch = require('@eluvio/elv-js-helpers/Functional/tryCatch')
const resultToPOJO = require('@eluvio/elv-js-helpers/Conversion/resultToPOJO')
// Using tryCatch to create safe versions of functions that may throw exceptions:
const firstChar = x => x.charAt(0)
const safeFirstChar = tryCatch(firstChar)
const goodResult1 = safeFirstChar('42')
goodResult1.inspect() //=> 'Ok "4"'
const errResult1 = safeFirstChar(42)
resultToPOJO(errResult1).ok //=> false
resultToPOJO(errResult1).errMsgs //=> ['TypeError: x.charAt is not a function']
// Class instance methods require .bind():
const myRegex = /^[a-z]+$/
const safeTest = tryCatch(myRegex.test.bind(myRegex))
const goodResult2 = safeTest('abc')
goodResult2.inspect() //=> 'Ok true'
safeTest('42').inspect() //=> 'Ok false'
const badResult2 = safeTest(Symbol())
resultToPOJO(badResult2).ok //=> false
resultToPOJO(badResult2).errMsgs //=> ['TypeError: Cannot convert a Symbol value to a string']
// Forgetting to use .bind() with a class instance method will cause obscure errors:
const badTest = tryCatch(myRegex.test)
const badTestResult = badTest('abc')
resultToPOJO(badTestResult).ok //=> false
resultToPOJO(badTestResult).errMsgs //=> ['TypeError: Method RegExp.prototype.test called on incompatible receiver undefined']
// Using tryCatch like a Javascript try / catch block (immediately executing the function):
// argument(s) listed inside tryCatch:
const goodResult3 = tryCatch(firstChar, '42')
goodResult3.inspect() //=> 'Ok "4"'
// argument(s) listed after tryCatch:
const badResult3 = tryCatch(firstChar)(42)
resultToPOJO(badResult3).ok //=> false
resultToPOJO(badResult3).errMsgs //=> ['TypeError: x.charAt is not a function'][*] → [*](unnamed)the array of elements
New list with only unique elements
Passthrough for Ramda's uniq function (Copyright © Scott Sauyet and Michael Hurley)
Allows users of elv-js-helpers to use the function without adding the Ramda
package as a dependency.
Returns a new list containing only one copy of each equivalent element in the original list.
Internally uses Ramda's equals function to compare elements for equivalency (available in elv-js-helpers as isEquivalent)
'use strict'
const uniq = require('@eluvio/elv-js-helpers/Functional/uniq')
uniq([1, 2, 3, 2]) //=> [1, 2, 3]
const obj1 = {foo: 'bar'}
const obj2 = {foo: 'bar'}
const obj3 = {bar: 'baz'}
uniq([obj1, obj2, obj3]) //=> [{foo: 'bar'}, {bar: 'baz'}]
// Strings are treated as arrays of characters
uniq('alphabet') //=> ['a', 'l', 'p', 'h', 'b', 'e', 't']
// Non-arrays are converted to empty array
uniq(99) //=> []* → String | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is:
If input passes validation, will return the input
Throws an exception if passed in an invalid value.
'use strict'
const UTCStrModel = require('@eluvio/elv-js-helpers/Model/UTCStrModel')
UTCStrModel('2022-01-01T14:00:00Z') //=> '2022-01-01T14:00:00Z'
UTCStrModel('2022-01-01T14:00:00.123Z') //=> '2022-01-01T14:00:00.123Z'
UTCStrModel('2022-13-01T14:00:00Z') //=> EXCEPTION: 'Value is not a valid UTC datetime string (got: "2022-13-01T14:00:00Z")'
UTCStrModel('foo') //=> EXCEPTION: `Value is not in UTC format 'yyyy-mm-ddThh:mm:ss[.s...]Z' (got: "foo")`
UTCStrModel(42) //=> EXCEPTION: 'expecting String, got Number 42'String → DateutcStringThe UTC timestamp to convert
Converts a string in UTC format (e.g. '2022-01-01T14:00:00Z') to a Javascript Date
Throws an exception if input is not a valid UTC string
'use strict'
const utcStrToDate = require('@eluvio/elv-js-helpers/Datetime/utcStrToDate')
const dateObject = utcStrToDate('2022-01-01T14:00:00Z')
dateObject.valueOf() //=> 1641045600000
utcStrToDate('2022-99-01T14:00:00Z') //=> EXCEPTION: 'Value is not a valid UTC datetime string (got: "2022-99-01T14:00:00Z")'
utcStrToDate(42) //=> EXCEPTION: 'expecting String, got Number 42'() → aThe uuid
Passthrough for the v4() function from uuid
_(Copyright © 2010-2020 Robert Kieffer and other contributors, MIT license) to generate a random UUID.
Allows users of elv-js-helpers to use the function without adding the uuid
package as a dependency.
The UUID generated will have lower case letters for hex digits.
'use strict'
const uuid = require('@eluvio/elv-js-helpers/Misc/uuid')
const RE_UUID_LOWER_CASE = require('@eluvio/elv-js-helpers/Validation/RE_UUID_LOWER_CASE')
const u = uuid()
u.length //=> 36
RE_UUID_LOWER_CASE.test(u) //=> true* → String | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is a Javascript String in UUID format e.g. '00000000-0000-0000-0000-000000000000' with only lower case letters for hex digits.
(Note that this is non-standard, RFC4122 specifies that both upper and lower case letters are acceptable)
Throws an exception if passed in an invalid value.
'use strict'
const UUIDStrLowerModel = require('@eluvio/elv-js-helpers/Model/UUIDStrLowerModel')
UUIDStrLowerModel('0') //=> EXCEPTION: `Value is not in lower case UUID format '00000000-0000-0000-0000-000000000000' (got: "0")`
UUIDStrLowerModel('ABCDEF00-0000-0000-0000-000000000000') //=> EXCEPTION: `Value is not in lower case UUID format '00000000-0000-0000-0000-000000000000' (got: "ABCDEF00-0000-0000-0000-000000000000")`
UUIDStrLowerModel('abcdef00-0000-0000-0000-000000000000') //=> 'abcdef00-0000-0000-0000-000000000000'
UUIDStrLowerModel('abcdef00-0000-0000-0000-ABCDEF000000') //=> EXCEPTION: `Value is not in lower case UUID format '00000000-0000-0000-0000-000000000000' (got: "abcdef00-0000-0000-0000-ABCDEF000000")`* → String | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is a Javascript String in UUID format e.g. '00000000-0000-0000-0000-000000000000'
Both upper and lower case letters are accepted for hex digits
Throws an exception if passed in an invalid value.
'use strict'
const UUIDStrModel = require('@eluvio/elv-js-helpers/Model/UUIDStrModel')
UUIDStrModel('0') //=> EXCEPTION: `Value is not in UUID format '00000000-0000-0000-0000-000000000000' (got: "0")`
UUIDStrModel('ABCDEF00-0000-0000-0000-000000000000') //=> 'ABCDEF00-0000-0000-0000-000000000000'
UUIDStrModel('abcdef00-0000-0000-0000-000000000000') //=> 'abcdef00-0000-0000-0000-000000000000'
UUIDStrModel('abcdef00-0000-0000-0000-ABCDEF000000') //=> 'abcdef00-0000-0000-0000-ABCDEF000000'* → String | THROW(unnamed)The input to validate
The validated input
An ObjectModel which validates that an input is a Javascript String in UUID format e.g. '00000000-0000-0000-0000-000000000000' with only upper case letters for hex digits.
(Note that this is non-standard, RFC4122 specifies that both upper and lower case letters are acceptable)
Throws an exception if passed in an invalid value.
'use strict'
const UUIDStrUpperModel = require('@eluvio/elv-js-helpers/Model/UUIDStrUpperModel')
UUIDStrUpperModel('0') //=> EXCEPTION: `Value is not in upper case UUID format '00000000-0000-0000-0000-000000000000' (got: "0")`
UUIDStrUpperModel('ABCDEF00-0000-0000-0000-000000000000') //=> 'ABCDEF00-0000-0000-0000-000000000000'
UUIDStrUpperModel('abcdef00-0000-0000-0000-000000000000') //=> EXCEPTION: `Value is not in upper case UUID format '00000000-0000-0000-0000-000000000000' (got: "abcdef00-0000-0000-0000-000000000000")`
UUIDStrUpperModel('abcdef00-0000-0000-0000-ABCDEF000000') //=> EXCEPTION: `Value is not in upper case UUID format '00000000-0000-0000-0000-000000000000' (got: "abcdef00-0000-0000-0000-ABCDEF000000")`Object → String → Result [String]objAn Object to check
propNameA property name to check
Validates that property name exists in an Object.
Returns a Crocks Result instance. This returned instance will be an Ok wrapping the field name if the property exists, or an Err wrapping an array containing an error message if property does not exist or if obj is not an Object (or if fieldname is not a string or symbol).
Function is curried, it can be called with just obj to return a validation function.
'use strict'
const validatePropName = require('@eluvio/elv-js-helpers/Validation/validatePropName')
const resultToPOJO = require('@eluvio/elv-js-helpers/Conversion/ResultToPOJO')
const myObj = {'foo': 1, 'bar': 2}
const goodResult = validatePropName(myObj, 'foo')
goodResult.inspect() //=> 'Ok "foo"'
resultToPOJO(goodResult).ok //=> true
resultToPOJO(goodResult).value //=> 'foo'
const errBadFieldName = validatePropName(myObj, 'baz')
resultToPOJO(errBadFieldName).ok //=> false
resultToPOJO(errBadFieldName).errMsgs //=> ['property "baz" not found']
const errNonObject = validatePropName(null, 'foo')
resultToPOJO(errNonObject).ok //=> false
resultToPOJO(errNonObject).errMsgs //=> ['Expecting object, got null']
// function is curried, call with just 1 argument to return a more specific validation function
const validateNameForMyObject = validatePropName(myObj)
validateNameForMyObject('bar').inspect() //=> 'Ok "bar"'
resultToPOJO(validateNameForMyObject(0)).ok //=> false
resultToPOJO(validateNameForMyObject('baz')).ok //=> falseModel → (a → Result [String] a)ModelAn ObjectModel definition to validate against
inputThe input to validate
Validates input against a Model and returns a
Crocks Result instance. This returned instance will be an
Ok wrapping the input data if it passed the Model's validations,
or an Err wrapping an array of validation errors.
Function is curried, it can be called with just Model to return a validation function.
'use strict'
const validateWithModel = require('@eluvio/elv-js-helpers/Validation/validateWithModel')
const PositiveNumModel = require('@eluvio/elv-js-helpers/Model/PositiveNumModel')
const resultToPOJO = require('@eluvio/elv-js-helpers/Conversion/ResultToPOJO')
const goodResult = validateWithModel(PositiveNumModel, 42)
goodResult.inspect() //=> 'Ok 42'
resultToPOJO(goodResult).ok //=> true
resultToPOJO(goodResult).value //=> 42
const errZeroInput = validateWithModel(PositiveNumModel, 0)
resultToPOJO(errZeroInput).ok //=> false
resultToPOJO(errZeroInput).errMsgs //=> ['PositiveNumber: Value must be > 0 (got: 0)']
const errStringInput = validateWithModel(PositiveNumModel, 'foo')
resultToPOJO(errStringInput).ok //=> false
resultToPOJO(errStringInput).errMsgs //=> ['PositiveNumber: expecting Number, got String "foo"']
// function is curried, call with just 1 argument to return a more specific validation function
const validatePositiveNumber = validateWithModel(PositiveNumModel)
validatePositiveNumber(42).inspect() //=> 'Ok 42'
resultToPOJO(validatePositiveNumber(0)).ok //=> false
resultToPOJO(validatePositiveNumber('foo')).ok //=> falseNon-array n => n | [a] → [n] | [a]xThe value to wrap in an array (if it is not already an array)
If value is not an array, returns an array containing the value, otherwise returns the original value
'use strict'
const wrapNonArray = require('@eluvio/elv-js-helpers/Conversion/wrapNonArray')
wrapNonArray(42) //=> [42]
wrapNonArray([42]) //=> [42]
wrapNonArray([0, 42]) //=> [0, 42]a → a → Boolean → Boolean → StringlowerBoundupperBoundlowerInclusiveWhether values are allowed to equal lowerBound
upperInclusiveWhether values are allowed to equal upperBound
Returns an error message for a failed upper bound condition
'use strict'
const _boundBetweenErrMsg = require('@eluvio/elv-js-helpers/ModelAssertion/_boundBetweenErrMsg')
_boundBetweenErrMsg(0, 42, true, true) //=> 'must be >= 0 and <= 42'
_boundBetweenErrMsg(0, 42, false, false) //=> 'must be > 0 and < 42'a → Boolean → StringlowerBoundinclusiveWhether values are allowed to equal lowerBound
Returns a description of a lower bound condition
'use strict'
const _boundLowerErrMsg = require('@eluvio/elv-js-helpers/ModelAssertion/_boundLowerErrMsg')
_boundLowerErrMsg(42, true) //=> 'must be >= 42'
_boundLowerErrMsg(42, false) //=> 'must be > 42'a → Boolean → StringupperBoundinclusiveWhether values are allowed to equal upperBound
Returns a description of an upper bound condition
'use strict'
const _boundUpperErrMsg = require('@eluvio/elv-js-helpers/ModelAssertion/_boundUpperErrMsg')
_boundUpperErrMsg(42, true) //=> 'must be <= 42'
_boundUpperErrMsg(42, false) //=> 'must be < 42'Model → ((Boolean, String) → String)keyModelThe Model to check keys against
Constructs an error message for failed key
Returns a function to be called by ObjectModel to construct an error message for a key that failed to validate against specified Model
'use strict'
const _objBadKeyErrMsg = require('@eluvio/elv-js-helpers/ModelAssertion/_objBadKeyErrMsg')
const defBasicModel = require('@eluvio/elv-js-helpers/ModelFactory/defBasicModel')
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
const passesModelCheck = require('@eluvio/elv-js-helpers/Boolean/passesModelCheck')
const NoBlankKeysObjModel = defBasicModel('NoBlankKeysObj', Object).extend()
.assert(
passesModelCheck(NonBlankStrModel),
_objBadKeyErrMsg(NonBlankStrModel)
)
NoBlankKeysObjModel({' ': 3}) //=> EXCEPTION: 'invalid property name " " (is not a valid NonBlankString)'Model → ((Boolean, String) → String)valueModelThe Model to check values against
Constructs an error message for failed value
Returns a function to be called by ObjectModel to construct an error message for a value that failed to validate against specified Model
'use strict'
const passesModelCheck = require('@eluvio/elv-js-helpers/Boolean/passesModelCheck')
const _objBadValErrMsg = require('@eluvio/elv-js-helpers/ModelAssertion/_objBadValErrMsg')
const NonBlankStrModel = require('@eluvio/elv-js-helpers/Model/NonBlankStrModel')
const defBasicModel = require('@eluvio/elv-js-helpers/ModelFactory/defBasicModel')
const NoBlankValuesObjModel = defBasicModel('NoBlankValuesObj', Object).extend()
.assert(
passesModelCheck(NonBlankStrModel),
_objBadValErrMsg(NonBlankStrModel)
)
NoBlankValuesObjModel({foo: ' '}) //=> EXCEPTION: 'key "foo" points to a value that is an invalid NonBlankString (NonBlankString: Value must not be a blank string (got: " "))'a → String | EXCEPTIONxThe value to inspect
If input value is a regular expression, returns the source (definition) of the expression. If input is a string, returns the string, escaped so that it can be used as to construct an exact match regexp. Otherwise throws an exception.
'use strict'
const _strOrRegExSrc = require('@eluvio/elv-js-helpers/Conversion/_strOrRegExSrc')
const RE_UUID_LOWER_CASE = require('@eluvio/elv-js-helpers/Validation/RE_UUID_LOWER_CASE')
_strOrRegExSrc(RE_UUID_LOWER_CASE) //=> '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
_strOrRegExSrc('foo') //=> 'foo'
_strOrRegExSrc(3) //=> EXCEPTION: 'Value is not a RegExp or string (3)'Err a | b → Err a | THROWxthe value to check
Throws an exception if anything but a Crocks Err is passed in. Otherwise does nothing and returns the Err
'use strict'
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
const _throwIfNotErr = require('@eluvio/elv-js-helpers/Validation/_throwIfNotErr')
_throwIfNotErr(42) //=> EXCEPTION: 'Expected an Err, got: Number (42)'
_throwIfNotErr(Ok(42)) //=> EXCEPTION: 'Expected an Err, got: Ok (Ok 42)'
// No exception thrown:
_throwIfNotErr(Err('foo'))Result a | b → Result a | THROWxthe value to check
Throws an exception if anything but a Crocks Result is passed in.
Otherwise returns the Result unchanged.
'use strict'
const _throwIfNotResult = require('@eluvio/elv-js-helpers/Validation/_throwIfNotResult')
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
_throwIfNotResult(42) //=> EXCEPTION: 'Expected a value of type Result, got: Number (42)'
_throwIfNotResult(Err(['42'])).inspect() //=> 'Err [ "42" ]'
_throwIfNotResult(Ok(42)).inspect() //=> 'Ok 42'a → BooleanReturns "Ok" if passed a Crocks Ok.
Returns "Err" if passed a Crocks Err.
Returns type(x) if passed anything else https://github.com/evilsoft/crocks/blob/master/src/core/type.js
Enables distinguishing between 'Err' and 'Ok' when examining Result instances.
NOTE: Use kind() if you need to check type of anything other than a
Crocks Result instance
(i.e. anything other than an Ok or Err).
'use strict'
const Err = require('@eluvio/elv-js-helpers/ADT/Err')
const Ok = require('@eluvio/elv-js-helpers/ADT/Ok')
const _typeWithOkErr = require('@eluvio/elv-js-helpers/Validation/_typeWithOkErr')
_typeWithOkErr(Err(['invalid query'])) //=> "Err"
_typeWithOkErr(Ok(42)) //=> "Ok"
// use kind() instead to check values other than Ok/Err!
_typeWithOkErr('foo') //=> "String"