(* → *) → ((*, *) → *) → ((*, *) → *)
(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.
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) //=> 84
Date → Number → Date
seconds
The number of seconds to add
datetime
Javascript Date object to add to
Adds a specified number of seconds to a Javascript Date object and returns a new Date
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.
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]
preCheckFn
The preliminary check that must pass in order for assertFn
to be checked.
assertFn
The assertion to check.
msgStrOrFn
An 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.
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]
model
The Model to be bounded
lowerBound
The lower bound that must be satisfied. If null
, no lower bound will be checked.
upperBound
The upper bound that must be satisfied. If null
, no upper bound will be checked.
lowerInclusive
If true
(and lowerBound
is not null
) then input is allowed to equal lowerBound
.
upperInclusive
If true
(and upperBound
is not null
) then input is allowed to equal upperBound
.
comparatorFn
Function 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.
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]
model
The Model to be bounded
lowerBound
The lower bound that must be satisfied.
upperBound
The upper bound that must be satisfied.
lowerInclusive
If true
then input is allowed to equal lowerBound
.
upperInclusive
If true
then input is allowed to equal upperBound
.
comparatorFn
Function 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.
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]
model
The Model to be bounded
lowerBound
The lower bound that must be satisfied.
inclusive
If true
(and lowerBound
is not null
) then input is allowed to equal lowerBound
.
comparatorFn
Function 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.
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]
model
The Model to be bounded
upperBound
The upper bound that must be satisfied.
inclusive
If true
(and upperBound
is not null
) then input is allowed to equal upperBound
.
comparatorFn
Function 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.
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.
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)
msg
Error 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)'
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]
model
The Model to add regex validation to
regex
The regex that must be matched.
errMsg
Optional 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.
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]
checkFn
A 2-input function that returns true
if the inputs are considered to be compatible,
false
otherwise.
errStrOrFn
Error 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
.
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.
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.
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]
keyModel
The 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.
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]
valueModel
The 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.
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]
orderingFn
A 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.
errStrOrFn
Error 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
.
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]
checkFn
A 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)
reqDesc
Description of required relation, e.g. 'must be greater than' - this will be used in error messages e.g. 'propertyName1 must be greater than propertyName2'
propertyName1
Name of attribute to check against propertyName2
propertyName2
Name 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.
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.
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 → Object
prop
The name of the property to set
computeFn
The function to use to compute value of prop
obj
The 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.
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 → Uint8Array
str
The 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.
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 → Uint8Array
bytes
The 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.
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.
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] → Integer
boolArray
An 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)
const boolsToInt = require('@eluvio/elv-js-helpers/Conversion/boolsToInt')
boolsToInt([false, false, true]) //=> 1
boolsToInt([true, false]) //=> 2
boolsToInt([true, true, true]) //=> 7
() → String
Returns 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).
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.
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'
* → *
x
the item to clone
Modified version of Ramda's clone
function (Copyright © 2013-2020 Scott Sauyet and Michael Hurley)
Uses original item's constructor function when input is an object.
Used to preserve ObjectModel constraints.
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 | 1
x
A string or an array whose elements can be compared with <
y
A 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.
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)
fn
the 2-input function (returning Boolean) to use for testing inputs
Copies name and functionality of Ramda's comparator
function (Copyright © 2013-2020 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.
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 | 1
x
A value that can be compared with <
y
A 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 < y
1
if y < x
0
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.
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') //= -1
a → b → -1 | 0 | 1
str1
A string representing a fraction or whole number
str2
A string representing a fraction or whole number
-1 | 0 | 1
Compares two strings x
and y
using fraction.js
and returns:
-1
if x < y
0
if x == y
(more specifically, if neither x < y
nor y < x
are true
)1
if y < x
Used as an input into sorting and validation functions.
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)
preCheckFn
A 1-input function - the precondition for checkFn
to take place
checkFn
A 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 false
The 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
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') //=> false
a → (() → 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.
const constant = require('@eluvio/elv-js-helpers/Functional/constant')
const always42 = constant(42)
always42() //=> 42
() → String
Returns name of function that it is called from. Used for introspection/logging
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.
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.
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)
name
the name of the generated Model
def
The 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
.
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)
name
the name of the generated Model
def
The 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)
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'
String → (Number | null) → (Number | null) → (Boolean | null) → (Boolean | null) → (* → Model | THROW)
name
the name of the generated Model
lowerBound
The lower bound (a string that is a valid FracStringModel) that must be satisfied. If null
, no lower bound will be checked.
upperBound
The upper bound (a string that is a valid FracStringModel) that must be satisfied. If null
, no upper bound will be checked.
lowerInclusive
If true
(and lowerBound
is not null
) then input is allowed to equal lowerBound
.
upperInclusive
If 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'
.
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)
name
the name of the generated Model
lowerBound
The lower bound that must be satisfied. If null
, no lower bound will be checked.
upperBound
The upper bound that must be satisfied. If null
, no upper bound will be checked.
lowerInclusive
If true
(and lowerBound
is not null
) then input is allowed to equal lowerBound
.
upperInclusive
If 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.
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)
name
the name of the generated Model
lowerBound
The lower bound that must be satisfied. If null
, no lower bound will be checked.
upperBound
The upper bound that must be satisfied. If null
, no upper bound will be checked.
lowerInclusive
If true
(and lowerBound
is not null
) then input is allowed to equal lowerBound
.
upperInclusive
If 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.
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)
name
the name of the generated Model
def
The 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
.
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"'
String → Model → Model → (* → Object | THROW)
name
the name of the generated Model
keyModel
The Model to validate keys against
valueModel
The 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
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)
name
the name of the generated Model
def
The 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.
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'}
(String, RexExp, String | undefined) → (* → String | THROW)
name
the name of the generated Model
regex
The regex that must be matched
errMsg
Optional 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:
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)
name
the name of the generated Model
def
The 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.
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)
name
the name of the generated Model
keyModel
The Model to validate keys against
valueModel
The 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.
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
.
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
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 a
x
The 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.
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
// ]
// }`
* → String
str
The 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
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] Number
timeElapsed
The amount of Datetime taken so far
portionComplete
A 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.
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] Number
timeElapsed
The amount of Datetime taken so far
portionComplete
A 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.
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 → String
secondsLeft
The 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 '--'
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 → String
currentTime
Javascript Date object to use as current Datetime.
secondsLeft
The number of seconds remaining until completion
zone
The Datetime zone in which to express ETA
locales
The 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.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"
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 © 2013-2020 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.
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']
{} → a
false
Ignores input and always returns false
.
Used for composing functional workflows, often indicating 'never'.
const F = require('@eluvio/elv-js-helpers/Functional/F')
F(42) //=> false
F() //=> false
Model → * → Boolean
Model
The Model to test against
input
The 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.
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
(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.
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
* → String
value
The 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.
const format = require('@eluvio/elv-js-helpers/Conversion/format')
format(' ') //=> '" "'
format(42) //=> '42'
format(x => x*2) //=> '[Function (anonymous)]'
format(format) //=> '[Function: format]'
string → number
str
A string representing a fraction or whole number
Evaluates string as a rational number using fraction.js and converts to a number.
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') //=> 0
String | 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.
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.
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")'
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.
const List = require('@eluvio/elv-js-helpers/ADT/List')
const Pair = require('@eluvio/elv-js-helpers/ADT/Pair')
const fromPairs = require('@eluvio/elv-js-helpers/Conversion/fromPairs')
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 | Undefined
pathArray
the path to retrieve, expressed as an array
object
the object to retrieve path from
Value or undefined
Renamed passthrough for Ramda's path
function (Copyright © 2013-2020 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
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) //=> 3
Idx = String | Int | Symbol => Idx → Object | Array → a | Undefined
prop
the property (or index) to retrieve
item
the item to retrieve property or element from
Value or undefined
Renamed passthrough for Ramda's prop
function (Copyright © 2013-2020 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
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
Number → Number → Number
oldValue
starting (baseline) value
newValue
ending 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
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) //=> -Infinity
Array → Boolean
arr
The 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 © 2013-2020 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.
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'
a → a
x
The input value
The input value
Given an input, returns that input. Used for composing functional workflows, often indicating 'no-op'.
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)
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
* → 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.
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 → Boolean
x
The value to test
Returns true
if passed an array.
Returns false
if passed anything else
const isArray = require('@eluvio/elv-js-helpers/Boolean/isArray')
isArray([1, 2, 3]) //=> true
isArray(1, 2, 3) //=> false
isArray('foo') //=> false
a → Boolean
x
The value to test
Returns true
if passed a valid Base58 string.
Returns false
if passed anything else.
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) //=> true
a → → Boolean
(unnamed)
The value to test
Passthrough for the Ramda isEmpty
function (Copyright © 2013-2020 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.
const isEmpty = require('@eluvio/elv-js-helpers/Boolean/isEmpty')
isEmpty([42]) //=> false
isEmpty([]) //=> true
isEmpty('') //=> true
isEmpty(null) //=> false
isEmpty({}) //=> true
isEmpty({foo: 'bar'}) //=> false
a → Boolean
x
The 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.
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) //=> true
a → b → Boolean
(unnamed)
The first value to compare
(unnamed)
The second value to compare
Renamed passthrough for the Ramda equals
function (Copyright © 2013-2020 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) //=> false
a → Boolean
x
The value to test
Returns true
if passed a Crocks Err instance.
Returns false
if passed anything else
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') //=> false
a → Boolean
x
The value to test
Returns true
if passed a function.
Returns false
if passed anything else
const isFunction = require('@eluvio/elv-js-helpers/Boolean/isFunction')
isFunction([1, 2, 3]) //=> false
isFunction(1, 2, 3) //=> false
isFunction('foo') //=> false
isFunction(isFunction) //=> true
a → Boolean
x
The value to test
Returns true
if passed a GeneratorFunction.
Returns false
if passed anything else
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.
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
(* → *) → * → * → Boolean
preprocessFn
function to use to preprocess inputs, to allow them to be compared with >
value1
the first value to compare
value2
the 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
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.
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.
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.
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
* → Boolean
x
the 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.
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
* → Boolean
value
the 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 © 2013-2020 Scott Sauyet and Michael Hurley)
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) //=> true
a → → Boolean
(unnamed)
The value to test
Negated version of the Ramda isEmpty
function (Copyright © 2013-2020 Scott Sauyet and Michael Hurley)
Returns false
if a value is the empty value for its type, true
otherwise.
const isNotEmpty = require('@eluvio/elv-js-helpers/Boolean/isNotEmpty')
isNotEmpty([42]) //=> true
isNotEmpty([]) //=> false
isNotEmpty('') //=> false
isNotEmpty(null) //=> true
isNotEmpty({}) //=> false
isNotEmpty({foo: 'bar'}) //=> true
a → Boolean
x
The value to test
Returns true
if passed null
.
Returns false
if passed anything else
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) //=> true
a → Boolean
x
The value to test
Returns true
if passed a Number.
Returns false
if passed anything else
const isNumber = require('@eluvio/elv-js-helpers/Boolean/isNumber')
isNumber(1) //=> true
isNumber(Infinity) //=> true
isNumber(NaN) //=> true
isNumber('foo') //=> false
a → Boolean
x
The value to test
Returns true
if passed an object.
Returns false
if passed anything else
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) //=> true
String → * → Boolean
kindName
Lower case string expected when value is passed to kind-of.
x
The value to test
Returns true
if value is of the specified type, false
otherwise.
The type is determined using the kind function.
const isOfKind = require('@eluvio/elv-js-helpers/Boolean/isOfKind')
isOfKind('Array', [1, 2, 3]) //=> true
isOfKind('Array', 1, 2, 3) //=> false
isOfKind('Array', 'foo') //=> false
a → Boolean
x
The value to test
Returns true
if passed a Crocks Ok instance.
Returns false
if passed anything else
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') //=> false
a → Boolean
x
The value to test
Returns true
if passed a regular expression.
Returns false
if passed anything else
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) //=> true
a → Boolean
x
The value to test
Returns true
if passed a Crocks Result instance.
Returns false
if passed anything else
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') //=> false
a → Boolean
x
The value to test
Returns true
if passed a string.
Returns false
if passed anything else
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) //=> true
a → Boolean
x
The value to test
Returns true
if passed undefined
.
Returns false
if passed anything else
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) //=> true
a → 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.
const Just = require('@eluvio/elv-js-helpers/ADT/Just')
Just(42).inspect() //=> 'Just 42'
* → String
val
The 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
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'
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.
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
Maybe
s (i.e. Just
or Nothing
)
If the original function returns a Result
, then the inputs fed into the converted function must also be
Result
s (i.e. Ok
or Err
)
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.
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
Maybe
s (i.e. Just
or Nothing
)
If the original function returns a Result
, then the inputs fed into the converted function must also be
Result
s (i.e. Ok
or Err
)
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 → * → List
list
A Crocks List object
element
The 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
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.
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 → Object
fn
The function to execute to obtain new key
obj
The 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.
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 → Object
keyFn
The function to execute to obtain new key
valFn
The function to execute to obtain new value
obj
The 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.
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 → Object
fn
The function to execute to obtain new value
obj
The 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.
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
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 → * → Boolean
re
the regexp to use to test
value
the 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
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) //=> false
(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.
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 → Boolean
checkFn
2-input function that returns true
if the inputs pass check, false
otherwise
array
Array 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.
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.
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.
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.
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)'
() → Nothing
Passthrough 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.
const Nothing = require('@eluvio/elv-js-helpers/ADT/Nothing')
Nothing().inspect() //=> 'Nothing'
Nothing(42).inspect() //=> 'Nothing'
() → Date
Returns current datetime as a Javascript Date
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
* → 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.
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.
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.
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 | undefined
keyModel
The 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.
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] | undefined
valueModel
The 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.
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.
const ObjectModel = require('@eluvio/elv-js-helpers/Model/ObjectModel')
ObjectModel({foo: "bar"}) //=> {foo: "bar"}
ObjectModel('foo') //=> EXCEPTION: 'expecting Object, got String "foo"'
String → a → Boolean
key
The key to check for
x
The value to test
Returns true
if item is an object with the specified key.
Returns false
otherwise
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'}) //=> false
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.
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
.
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.
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.
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 → Date
utcString
The 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
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() //=> NaN
Model → * → Boolean
Model
The Model to test against
input
The 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.
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') //=> false
Model → * → Boolean
keyModel
the Model to check keys against
obj
The 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
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) //=> true
Model → * → Boolean
valueModel
the Model to check values against
obj
The 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
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.
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'}
((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.
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()
.
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=json
* → * | 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.
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.
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.
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) → a
value
The value to redact
addlPatterns
Any additional patters to test keys against
parentKey
the 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.
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]"}'
Type:Array.<RegExp>"[{},{},{},{},{},{},{},{},{},{},{}]"
Array of Regular Expressions
used by redact()
to decide whether a particular object attribute should have its value redacted.
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
[string], …stringsAndOrRegExps → RegExp | EXCEPTION
Javascript tagged template function to allow composing regular expressions.
Throws an exception if all sub-regexes do not have the same flags.
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') //=> false
Result [e] a → Object
result
The 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)
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 | a
x
The 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
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)) //=> 42
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()
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') //=> false
Type: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.
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.
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.123
Type: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.
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') //=> true
Type: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)
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') //=> false
Type: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)
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') //=> false
a → Boolean → ((a, a) → Integer) → a → Boolean
lowerBound
the lower bound to be satisfied
upperBound
the upper bound to be satisfied
lowerInclusive
if true
, then value
is allowed equal lowerBound
upperInclusive
if true
, then value
is allowed equal upperBound
comparatorFn
The 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.
value
The 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
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) //=> false
a → Boolean → ((a, a) → Integer) → a → Boolean
lowerBound
the lower bound to be satisfied
inclusive
if true
, then value
is allowed equal lowerBound
comparatorFn
The 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.
value
The 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
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) //=> true
a → Boolean → ((a, a) → Integer) → a → Boolean
upperBound
the upper bound to be satisfied
inclusive
if true
, then value
is allowed equal upperBound
comparatorFn
The 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.
value
The 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
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) //=> false
Number → ((*) → 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.
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) //=> 42
Idx = String | Int | Symbol => [Idx] → * → Object → Object
pathArray
the path to set, expressed as an array
value
the value to store at path
object
the original object
Shallow copy of object
with
Renamed passthrough for Ramda's assocPath
function (Copyright © 2013-2020 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
.
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"
* → 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.
const StringModel = require('@eluvio/elv-js-helpers/Model/StringModel')
StringModel('foo') //=> 'foo'
StringModel(42) //=> EXCEPTION: 'expecting String, got Number 42'
() → String
Returns locale string from current environment (see http://www.lingoes.net/en/translator/langcode.htm)
The locale string is used to format dates and times
const sysLocale = require('@eluvio/elv-js-helpers/Datetime/sysLocale')
sysLocale() //=> 'en-US'
() → String
Returns Datetime zone string from current environment
const sysTimezone = require('@eluvio/elv-js-helpers/Datetime/sysTimezone')
sysTimezone() //=> 'America/Los_Angeles'
{} → a
true
Ignores input and always returns true.
Used for composing functional workflows, often indicating 'always'.
const T = require('@eluvio/elv-js-helpers/Functional/T')
T(42) //=> true
T() //=> true
String → THROW
message
Error message for exception
Throws an exception. Used to allow terser code, e.g. replacing if
/else
with a ternary expression.
const throwError = require('@eluvio/elv-js-helpers/Misc/throwError')
throwError('clear and helpful error message') //=> EXCEPTION: 'clear and helpful error message'
ObjectOrModel → * → undefined | THROW
modelOrObj
a Model or an Object that can be used as an ObjectModel spec
args
the 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.
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 | THROW
message
the error message to use in the exception
value
the 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.
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 | THROW
message
the error message to use in the exception
value
the 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.
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) //=> 0
String → a → a | THROW
message
the error message to use in the exception
value
the value to check if undefined
Throws an exception with the specified message if undefined
is passed in.
Otherwise returns the value unchanged.
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 → Boolean
fn
The function to test
Returns true
if fn()
throws an exception when called.
Returns false
otherwise.
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]
fn
the function to call with index
repeatCount
the number of times to call the function
List with result of function call(s)
Passthrough for Ramda's times
function (Copyright © 2013-2020 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.
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)
locales
The locales
argument to pass to Date.toLocaleString()
options
The 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.
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.
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] → *
choiceArray
An array of items to choose from
boolArray
An 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' |
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 b
fn
The 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)()
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.exec called on incompatible receiver #<Object>']
// 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 © 2013-2020 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
)
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.
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 → Date
utcString
The 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
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'
() → a
The 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.
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.
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.
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.
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")`
Model → (a → Result [String] a)
Model
An ObjectModel definition to validate against
input
The 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.
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 //=> false
Non-array n => n | [a] → [n] | [a]
x
The 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
const wrapNonArray = require('@eluvio/elv-js-helpers/Conversion/wrapNonArray')
wrapNonArray(42) //=> [42]
wrapNonArray([42]) //=> [42]
wrapNonArray([0, 42]) //=> [0, 42]
a → a → Boolean → Boolean → String
lowerBound
upperBound
lowerInclusive
Whether values are allowed to equal lowerBound
upperInclusive
Whether values are allowed to equal upperBound
Returns an error message for a failed upper bound condition
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 → String
lowerBound
inclusive
Whether values are allowed to equal lowerBound
Returns a description of a lower bound condition
const _boundLowerErrMsg = require('@eluvio/elv-js-helpers/ModelAssertion/_boundLowerErrMsg')
_boundLowerErrMsg(42, true) //=> 'must be >= 42'
_boundLowerErrMsg(42, false) //=> 'must be > 42'
a → Boolean → String
upperBound
inclusive
Whether values are allowed to equal upperBound
Returns a description of an upper bound condition
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)
keyModel
The 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
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)
valueModel
The 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
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 | EXCEPTION
x
The 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.
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 | THROW
x
the value to check
Throws an exception if anything but a Crocks Err is passed in. Otherwise does nothing and returns the Err
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 | THROW
x
the value to check
Throws an exception if anything but a Crocks Result is passed in.
Otherwise returns the Result
unchanged.
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 → Boolean
Returns "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
).
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"