addPreprocessFn2Functional

(* → *) → ((*, *) → *) → ((*, *) → *)
λcurried function
Parameters
  • function(unnamed)

    The 1-input preprocessing function

  • function(unnamed)

    The 2-input function to add preprocessor to

  • Returns:function

    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

addSecondsDatetime

Date → Number → Date
λcurried function
Parameters
  • Numberseconds

    The number of seconds to add

  • Datedatetime

    Javascript Date object to add to

  • Returns:Date

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'

andFunctional

(a → Boolean | Pred a) → (a → Boolean | Pred a) → a → Boolean
λcurried function
Parameters
  • function(unnamed)

    First function that returns a Boolean

  • function(unnamed)

    Second function that returns a Boolean

  • Returns:function

    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

AnyModelModel

* → *
Parameters
  • Any(unnamed)

    Any input

  • Returns:*

    The input

Passthrough for Any model from ObjectModel (Copyright © 2015 Sylvain Pollet-Villard, MIT license)

Used to define fields that can hold any type.

assertAfterCheckModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → (a → Boolean) → String → [(* → Boolean), ObjectModelErrMsgFn | String]
Parameters
  • functionpreCheckFn

    The preliminary check that must pass in order for assertFn to be checked.

  • functionassertFn

    The assertion to check.

  • StringmsgStrOrFn

    An error message string or message generating function to use if assertFn returns false.

  • Returns:Array

    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 false
  • false if assertFn returns false for the input AND preCheckFn returns true

This 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")'

assertBoundedModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → a → a → Boolean → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]
Parameters
  • Modelmodel

    The Model to be bounded

  • AnylowerBound

    The lower bound that must be satisfied. If null, no lower bound will be checked.

  • AnyupperBound

    The upper bound that must be satisfied. If null, no upper bound will be checked.

  • BooleanlowerInclusive

    If true (and lowerBound is not null) then input is allowed to equal lowerBound.

  • BooleanupperInclusive

    If true (and upperBound is not null) then input is allowed to equal upperBound.

  • functioncomparatorFn

    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.

  • Returns:Array

    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 bounded
  • false 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)'

assertBoundedBetweenModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → a → a → Boolean → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]
Parameters
  • Modelmodel

    The Model to be bounded

  • AnylowerBound

    The lower bound that must be satisfied.

  • AnyupperBound

    The upper bound that must be satisfied.

  • BooleanlowerInclusive

    If true then input is allowed to equal lowerBound.

  • BooleanupperInclusive

    If true then input is allowed to equal upperBound.

  • functioncomparatorFn

    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.

  • Returns:Array

    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 bounded
  • false 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"'

assertBoundedLowerModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → a → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]
Parameters
  • Modelmodel

    The Model to be bounded

  • AnylowerBound

    The lower bound that must be satisfied.

  • Booleaninclusive

    If true (and lowerBound is not null) then input is allowed to equal lowerBound.

  • functioncomparatorFn

    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.

  • Returns:Array

    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 bounded
  • false 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"'

assertBoundedUpperModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → a → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]
Parameters
  • Modelmodel

    The Model to be bounded

  • AnyupperBound

    The upper bound that must be satisfied.

  • Booleaninclusive

    If true (and upperBound is not null) then input is allowed to equal upperBound.

  • functioncomparatorFn

    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.

  • Returns:Array

    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 bounded
  • false 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"'

assertEmptyModelAssertion

() → [(* → Boolean), String]
Parameters
  • Returns:Array

    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 empty
  • false if the input is NOT empty

The 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 []'

assertionErrMsgModelAssertion

String → ((Boolean, *, String) → String)
Parameters
  • Stringmsg

    Error message describing the assertion condition that was not met

  • Returns:function

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)'

assertMatchesRegexModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → RegExp → [(* → Boolean), ObjectModelErrMsgFn]
Parameters
  • Modelmodel

    The Model to add regex validation to

  • RegExpregex

    The regex that must be matched.

  • StringerrMsg

    Optional custom error message

  • Returns:Array

    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 bounded
  • false 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'

assertNeighborsPassModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => ((*, *) → Boolean) → (Function | String) → [([*] → Boolean), ObjectModelErrMsgFn | String]
Parameters
  • functioncheckFn

    A 2-input function that returns true if the inputs are considered to be compatible, false otherwise.

  • functionerrStrOrFn

    Error message to use when ordering check fails.

  • Returns:Array

    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 array
  • false 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"'

assertNotEmptyModelAssertion

() → [(* → Boolean), String]
Parameters
  • Returns:Array

    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 empty
  • false if the input is empty

The 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 []'

assertNothingModelAssertion

() → [(* → Boolean), String]
Parameters
  • Returns:Array

    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, '']

assertObjKeysValidModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → * → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]
Parameters
  • ModelkeyModel

    The Model to check keys against

  • Returns:Array

    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 object
  • false if the input IS a Javascript object AND has a key (property name) that violates specified Model

This 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)'

assertObjValuesValidModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → * → Boolean → [(* → Boolean), ObjectModelErrMsgFn | String]
Parameters
  • ModelvalueModel

    The Model to check values against

  • Returns:Array

    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 object
  • false if the the input IS a Javascript object AND has a value that violates specified Model

This 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: "  "))'

assertOrderedModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => ((*, *) → Boolean) → (Function | String) → [([*] → Boolean), ObjectModelErrMsgFn | String]
Parameters
  • functionorderingFn

    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.

  • functionerrStrOrFn

    Error message to use when ordering check fails.

  • Returns:Array

    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 array
  • false 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"'

assertPropRelModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => Model → ((b, a) → Boolean) → String → String → String → [(* → Boolean), ObjectModelErrMsgFn | String]
λcurried function
Parameters
  • functioncheckFn

    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)

  • StringreqDesc

    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'

  • StringpropertyName1

    Name of attribute to check against propertyName2

  • StringpropertyName2

    Name of attribute to check against propertyName1

  • Returns:Array

    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 object
  • false if the input is an object AND violates the specified property relationship

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. 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)'

assertValidUTCStrModelAssertion

((Boolean, *, String) → String) ObjectModelErrMsgFn => () → [(* → Boolean), ObjectModelErrMsgFn]
Parameters
  • Returns:Array

    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 NonBlankStrModel
  • false 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")'

assocComputedFunctional

String → Function → Object → Object
λcurried function
Parameters
  • Stringprop

    The name of the property to set

  • functioncomputeFn

    The function to use to compute value of prop

  • Objectobj

    The object to copy and use as input to computeFn

  • Returns:Object

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}

AsyncADT

((e → (), a → ()) → ()) → Async e a
((e → (), a → ()) → (() → ()) → Async e a
Parameters
  • function(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.

  • Returns:Async

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')

base58DecodeConversion

String → Uint8Array
Parameters
  • Stringstr

    The base-58 string to decode

  • Returns:Uint8Array

    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'

base58EncodeConversion

String → Uint8Array
Parameters
  • Uint8Arraybytes

    The bytes to encode

  • Returns:String

    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'

Base58StrModelModel

* → String | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:String

    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'

boolsToIntConversion

[Boolean] → Integer
Parameters
  • Array.<Boolean>boolArray

    An array of booleans representing binary digits of a non-negative integer (most significant bit first)

  • Returns:Integer

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

callerFuncNameMisc

() → 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'

chainFunctional

(a → m b) → m a → m b
λcurried function
Parameters
  • function(unnamed)

    A curried function that takes a 'normal' value and returns a wrapped value)

  • Object(unnamed)

    Instance of Functional data type to pass into function

  • Returns:*

    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'

cloneFunctional

* → *
Parameters
  • Objectx

    the item to clone

  • Returns:Object

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'

cmpIndexableFunctional

[a] → [b] → -1 | 0 | 1
λcurried function
Parameters
  • Arrayx

    A string or an array whose elements can be compared with <

  • Arrayy

    A string or an array whose elements can be compared with <

  • Returns:Integer

    -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'

comparatorFunctional

(a → a → Boolean) → (a → b → -1 | 0 | 1)
Parameters
  • functionfn

    the 2-input function (returning Boolean) to use for testing inputs

  • Returns:function
    • a 2-input comparator function that returns -1, 0, or 1

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]

compareFunctional

a → b → -1 | 0 | 1
λcurried function
Parameters
  • Anyx

    A value that can be compared with <

  • Anyy

    A value that can be compared with <

  • Returns:Integer

    -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

compareFracStrFunctional

a → b → -1 | 0 | 1
λcurried function
Parameters
  • Stringstr1

    A string representing a fraction or whole number

  • Stringstr2

    A string representing a fraction or whole number

  • Returns:Integer

    -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'

conditionalCheckBoolean

(* → Boolean) → (* → Boolean) → (* → Boolean)
Parameters
  • functionpreCheckFn

    A 1-input function - the precondition for checkFn to take place

  • functioncheckFn

    A 1-input function - the actual check to perform

  • Returns:function

Creates a function that:

  • Returns true if preCheckFn is false or checkFn is true.
  • Returns 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

constantFunctional

a → (() → a)
Parameters
  • Any(unnamed)

    The value to always return

  • Returns:function

    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

currentFuncNameMisc

() → 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'

curryFunctional

((a, b, …) → z) → a → b → … → z
Parameters
  • function(unnamed)

    The function to curry

  • Returns:function

    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

DatetimeModelModel

* → Date | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:Date

    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"'

defArrayModelModelFactory

String → ([Model] | Model) → (* → Array | THROW)
Parameters
  • Stringname

    the name of the generated Model

  • Array.<Model>def

    The type/Model or array of types/Model that are valid for elements

  • Returns:Object

    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:

  • A Javascript Array
  • Made up of elements that are of the specified type definition(s)

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"'

defBasicModelModelFactory

String → ([Model] | Model) → (* → Array | THROW)
Parameters
  • Stringname

    the name of the generated Model

  • Array.<Model>def

    The type/Model or array of types/Model that are valid for input

  • Returns:Object

    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'

defBoundedFracStrModelModelFactory

String → (Number | null) → (Number | null) → (Boolean | null) → (Boolean | null) → (* → Model | THROW)
Parameters
  • Stringname

    the name of the generated Model

  • StringlowerBound

    The lower bound (a string that is a valid FracStringModel) that must be satisfied. If null, no lower bound will be checked.

  • StringupperBound

    The upper bound (a string that is a valid FracStringModel) that must be satisfied. If null, no upper bound will be checked.

  • BooleanlowerInclusive

    If true (and lowerBound is not null) then input is allowed to equal lowerBound.

  • BooleanupperInclusive

    If true (and upperBound is not null) then input is allowed to equal upperBound.

  • Returns:Model

Returns an ObjectModel which will validate that an input is:

  • A Javascript String
  • In the form of a whole number or fraction 'x', '-x', 'x/y' or '-x/y', y !=0
  • Greater than a specified lower bound (if specified) or equal to the lower bound (if lower inclusivity is specified)
  • Less than a specified upper bound (if specified) or equal to the upper bound (if upper inclusivity is specified)

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'

defBoundedIntModelModelFactory

String → (Number | null) → (Number | null) → (Boolean | null) → (Boolean | null) → (* → Integer | THROW)
Parameters
  • Stringname

    the name of the generated Model

  • NumberlowerBound

    The lower bound that must be satisfied. If null, no lower bound will be checked.

  • NumberupperBound

    The upper bound that must be satisfied. If null, no upper bound will be checked.

  • BooleanlowerInclusive

    If true (and lowerBound is not null) then input is allowed to equal lowerBound.

  • BooleanupperInclusive

    If true (and upperBound is not null) then input is allowed to equal upperBound.

  • Returns:function

    Returns an ObjectModel that can be called with an input

Returns an ObjectModel which will validate that an input is:

  • A Javascript Number
  • An integer
  • Greater than a specified lower bound (if specified) or equal to the lower bound (if lower inclusivity is specified)
  • Less than a specified upper bound (if specified) or equal to the upper bound (if upper inclusivity is specified)

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"'

defBoundedNumModelModelFactory

String → (Number | null) → (Number | null) → (Boolean | null) → (Boolean | null) → (* → Model | THROW)
Parameters
  • Stringname

    the name of the generated Model

  • NumberlowerBound

    The lower bound that must be satisfied. If null, no lower bound will be checked.

  • NumberupperBound

    The upper bound that must be satisfied. If null, no upper bound will be checked.

  • BooleanlowerInclusive

    If true (and lowerBound is not null) then input is allowed to equal lowerBound.

  • BooleanupperInclusive

    If true (and upperBound is not null) then input is allowed to equal upperBound.

  • Returns:Model

Returns an ObjectModel which will validate that an input is:

  • A Javascript Number
  • Greater than a specified lower bound (if specified) or equal to the lower bound (if lower inclusivity is specified)
  • Less than a specified upper bound (if specified) or equal to the upper bound (if upper inclusivity is specified)

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"'

defNonEmptyArrModelModelFactory

String → ([Model] | Model) → (* → Array | THROW)
Parameters
  • Stringname

    the name of the generated Model

  • Array.<Model>def

    The type/Model or array of types/Model that elements

  • Returns:Object

    Returns an ObjectModel that can be called with an input

Returns an ObjectModel which will validate that an input is:

  • A Javascript Array
  • Made up of elements that are of the specified type definition(s)

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"'

defNonEmptyTypedKVObjModelModelFactory

String → Model → Model → (* → Object | THROW)
Parameters
  • Stringname

    the name of the generated Model

  • ModelkeyModel

    The Model to validate keys against

  • ModelvalueModel

    The Model to validate values against

  • Returns:Object

    Returns an ObjectModel that can be called with an input

Returns an ObjectModel which will validate that an input is:

  • A Javascript Object
  • Has keys that validate against a Model
  • Has values that validate against a Model
  • Has at least one key

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: {})'

defObjectModelModelFactory

String → Object → (* → Object | THROW)
Parameters
  • Stringname

    the name of the generated Model

  • Objectdef

    The definition (field structure) of the Model to generate

  • Returns:Object

    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'}

defRegexMatchedStrModelModelFactory

(String, RexExp, String | undefined) → (* → String | THROW)
Parameters
  • Stringname

    the name of the generated Model

  • RegExpregex

    The regex that must be matched

  • StringerrMsg

    Optional custom error message string (if omitted, regex will be included as part of standard error message)

  • Returns:function

    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")'

defSealedObjModelModelFactory

String → Object → (* → Object | THROW)
Parameters
  • Stringname

    the name of the generated Model

  • Objectdef

    The definition (field structure) of the Model to generate

  • Returns:function

    Returns an ObjectModel that can be called with an input

Returns an ObjectModel which will validate that an input is:

  • A Javascript Object
  • Satisfies the specified field definitions
  • Contains no extra fields

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'

defTypedKVObjModelModelFactory

String → Model → Model → (* → Object | THROW)
Parameters
  • Stringname

    the name of the generated Model

  • ModelkeyModel

    The Model to validate keys against

  • ModelvalueModel

    The Model to validate values against

  • Returns:Object

    Returns an ObjectModel that can be called with an input

Returns an ObjectModel which will validate that an input is:

  • A Javascript Object
  • Has keys that validate against a Model
  • Has values that validate against a Model

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'

dumpJSONMisc

* → 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

eitherFunctional

(errVal → x) → (okVal → x) → Result errVal okVal → x
Parameters
  • function(unnamed)

    The function to apply to value contained in an Err

  • function(unnamed)

    The function to apply to value contained in an Ok

  • Returns:function

    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)'

ErrADT

a → Err a
Parameters
  • Anyx

    The value to wrap in an Err

  • Returns:Result

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
                                                              //              ]
                                                              //            }`

escapeForRegExpConversion

* → String
Parameters
  • stringstr

    The value to escape

  • Returns:string

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'

estRemainingDurDatetime

Number → Number → Result [String] Number
Parameters
  • numbertimeElapsed

    The amount of Datetime taken so far

  • numberportionComplete

    A number between 0 and 1 (inclusive) representing progress

  • Returns:number

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)']

estTotalDurDatetime

Number → Number → Result [String] Number
Parameters
  • numbertimeElapsed

    The amount of Datetime taken so far

  • numberportionComplete

    A number between 0 and 1 (inclusive) representing progress

  • Returns:number

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)']

etaDurStrDatetime

Number → String
Parameters
  • numbersecondsLeft

    The number of seconds remaining until completion

  • Returns:string

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)     //=> "--"

etaTimeStrDatetime

Date → Number → String
Parameters
  • DatecurrentTime

    Javascript Date object to use as current Datetime.

  • NumbersecondsLeft

    The number of seconds remaining until completion

  • Stringzone

    The Datetime zone in which to express ETA

  • Stringlocales

    The locale to use to format ETA

  • Returns:String

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,

  • Bad values for currentTime / zone will return 'Invalid DateTime'
  • Unrecognized locale strings in locales will be ignored, and if none are recognized, it will be obtained from the system environment.
  • Passing in a value of incorrect type for 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"

exportsFunctional

Ord b => (a → b) → [a] → [a]
λcurried function
Parameters
  • function(unnamed)

    the function to obtain the sort key for each element

  • Array(unnamed)

    the list to sort

  • Returns:Array

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']

FFunctional

{} → a
Parameters
  • Returns:Boolean

    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

failsModelCheckBoolean

Model → * → Boolean
λcurried function
Parameters
  • ModelModel

    The Model to test against

  • Anyinput

    The value to test

  • Returns:Boolean

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

flipFunctional

(a → b → c) → b → a → c
λcurried function
Parameters
  • function(unnamed)

    A 2-input function

  • Returns:function
    • A curried 2-input function that reverses the order of inputs before passing to the original 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

formatConversion

* → String
Parameters
  • Anyvalue

    The value to format

  • Returns:String

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]'

fracStrToNumConversion

string → number
Parameters
  • Stringstr

    A string representing a fraction or whole number

  • Returns: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

fractionConversion

String | Number → Object
Parameters
  • String(unnamed)

    The value to convert into a fraction.js object

  • Returns: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

FractionStrModelModel

* → String | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:String

    The validated input

An ObjectModel which validates that an input is:

  • A Javascript String
  • Is in the form 'x/y', '-x/y', 'x', or '-x' where x and y are integers and y != 0

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")'

fromPairsConversion

List (Pair String a) → Object
Parameters
  • List(unnamed)

    The List of key, value Pairs

  • Returns:Object

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 }

FunctionModelModel

* → *
Parameters
  • Any(unnamed)

    Any input

  • Returns:*

    The input

Validates that an input is a function

getPathFunctional

Idx = String | Int | Symbol => [Idx] → {a} → a | Undefined
λcurried function
Parameters
  • ArraypathArray

    the path to retrieve, expressed as an array

  • Objectobject

    the object to retrieve path from

  • Returns:*

    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

getPropFunctional

Idx = String | Int | Symbol => Idx → Object | Array → a | Undefined
λcurried function
Parameters
  • Stringprop

    the property (or index) to retrieve

  • Objectitem

    the item to retrieve property or element from

  • Returns:*

    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

growthMath

Number → Number → Number
λcurried function
Parameters
  • NumberoldValue

    starting (baseline) value

  • NumbernewValue

    ending value for calculating growth amount

  • Returns:Number

    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.:

  • Returns 0 if both values are the same
  • Returns 0.5 if second value is 50% bigger than the first value
  • Returns -0.5 if second value is 50% smaller than the first value

Note 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 negative
  • 0 if the second value is zero

Note 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

hasNoDuplicatesBoolean

Array → Boolean
Parameters
  • Arrayarr

    The value to test

  • Returns:Boolean

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'

identityFunctional

a → a
Parameters
  • Anyx

    The input value

  • Returns:*

    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

ifElseFunctional

(a → boolean) → (a → b) → (a → b) → a → b
Parameters
  • function(unnamed)

    The boolean test function

  • function(unnamed)

    The function to apply to value if test function returns true

  • function(unnamed)

    The function to apply to value if test function returns false

  • Returns:function

    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

IntegerModelModel

* → Integer | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:Integer

    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)'

isArrayBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isBase58StringBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isEmptyBoolean

a → → Boolean
λcurried function
Parameters
  • Any(unnamed)

    The value to test

  • Returns:Boolean

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

isEqualBoolean

a → Boolean
λcurried function
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isEquivalentBoolean

a → b → Boolean
λcurried function
Parameters
  • Any(unnamed)

    The first value to compare

  • Any(unnamed)

    The second value to compare

  • Returns:Boolean

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

isErrBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isFunctionBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isGeneratorFunctionBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isGTBoolean

* → * → Boolean
λcurried function
Parameters
  • Any(unnamed)

    the first value to compare

  • Any(unnamed)

    the second value to compare

  • Returns:Boolean

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

isGTCustomBoolean

(* → *) → * → * → Boolean
λcurried function
Parameters
  • functionpreprocessFn

    function to use to preprocess inputs, to allow them to be compared with >

  • Anyvalue1

    the first value to compare

  • Anyvalue2

    the second value to compare

  • Returns:Boolean

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

isGTEBoolean

* → * → Boolean
λcurried function
Parameters
  • Any(unnamed)

    the first value to compare

  • Any(unnamed)

    the second value to compare

  • Returns:Boolean

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

isLTBoolean

* → * → Boolean
λcurried function
Parameters
  • Any(unnamed)

    the first value to compare

  • Any(unnamed)

    the second value to compare

  • Returns:Boolean

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

isLTEBoolean

* → * → Boolean
λcurried function
Parameters
  • Any(unnamed)

    the first value to compare

  • Any(unnamed)

    the second value to compare

  • Returns:Boolean

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

isModelBoolean

* → Boolean
Parameters
  • Anyx

    the item to check

  • Returns:Boolean

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

isNilBoolean

* → Boolean
Parameters
  • Anyvalue

    the value to test

  • Returns:Boolean

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

isNotEmptyBoolean

a → → Boolean
λcurried function
Parameters
  • Any(unnamed)

    The value to test

  • Returns:Boolean

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

isNullBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isNumberBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isObjectBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isOfKindBoolean

String → * → Boolean
λcurried function
Parameters
  • StringkindName

    Lower case string expected when value is passed to kind-of.

  • Anyx

    The value to test

  • Returns:Boolean

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

isOkBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isRegExpBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isResultBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isStringBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

isUndefinedBoolean

a → Boolean
Parameters
  • Anyx

    The value to test

  • Returns:Boolean

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

JustADT

a → Just a
Parameters
  • Any(unnamed)

    The value to wrap in a Just

  • Returns:Maybe

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'

kindValidation

* → String
Parameters
  • Anyval

    The item to evaluate

  • Returns:String

    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'

liftA2Functional

Applicative m => (a → b → c) → m a → m b → m c
λcurried function
Parameters
  • function(unnamed)

    The 2-input curried function to lift

  • Returns:function

    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'

liftA2JoinFunctional

Function → Function
λcurried function
Parameters
  • function(unnamed)

    A function which takes 2 'normal' values and returns a wrapped value (e.g. a Crocks Result)

  • Returns:function

    New function which takes 2 wrapped values and returns a wrapped value

Converts a function which accepts 2 'normal' values and returns a wrapped value (i.e. an ADT) into a function that takes 2 wrapped values and returns a wrapped value.

This is similar to the liftA2 function, except that it avoids adding an extra layer of wrapping to the returned value.

NOTE: The original function must be curried.

Note that the wrapper type of the inputs must be the same as the wrapper type returned by the function.

For example, if the original function returns a Maybe, then the inputs fed into the converted function must also be Maybes (i.e. Just or Nothing)

If the original function returns a Result, then the inputs fed into the converted function must also be Results (i.e. Ok or Err)

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" ]'

liftA3Functional

Applicative m => (a → b → c → d) → m a → m b → m c → m d
λcurried function
Parameters
  • function(unnamed)

    The 3-input curried function to lift

  • Returns:function

    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'

liftA3JoinFunctional

Function → Function
λcurried function
Parameters
  • function(unnamed)

    A function which takes 3 'normal' values and returns a wrapped value (e.g. a Crocks Result)

  • Returns:function

    New function which takes 3 wrapped values and returns a wrapped value

Converts a function which accepts 3 'normal' values and returns a wrapped value (i.e. an ADT) into a function that takes 3 wrapped values and returns a wrapped value.

This is similar to the liftA3 function, except that it avoids adding an extra layer of wrapping to the returned value.

NOTE: The original function must be curried.

Note that the wrapper type of the inputs must be the same as the wrapper type returned by the function.

For example, if the original function returns a Maybe, then the inputs fed into the converted function must also be Maybes (i.e. Just or Nothing)

If the original function returns a Result, then the inputs fed into the converted function must also be Results (i.e. Ok or Err)

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" ]'

ListADT

* → List *
Parameters
  • Any(unnamed)

    The value to wrap in a List

  • Returns: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'

listPushFunctional

List → * → List
λcurried function
Parameters
  • Listlist

    A Crocks List object

  • Anyelement

    The item to add to end of list

  • Returns: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 ]'

mapFunctional

(a → b) → m a → m b
λcurried function
Parameters
  • function(unnamed)

    A curried function that takes a 'normal' value and returns a 'normal' value)

  • Object(unnamed)

    Instance of Functional data type to pass into function

  • Returns:*

    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" ]'

mapObjKeysFunctional

((String, *, Object) → *) → Object → Object
λcurried function
Parameters
  • functionfn

    The function to execute to obtain new key

  • Objectobj

    The object to process

  • Returns:Object

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}'

mapObjKVFunctional

((String, *, Object) → *) → ((*, String, Object) → *) → Object → Object
λcurried function
Parameters
  • functionkeyFn

    The function to execute to obtain new key

  • functionvalFn

    The function to execute to obtain new value

  • Objectobj

    The object to process

  • Returns:Object

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}'

mapObjValuesFunctional

((*, String, Object) → *) → Object → Object
λcurried function
Parameters
  • functionfn

    The function to execute to obtain new value

  • Objectobj

    The object to process

  • Returns:Object

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}'

mapWithIndexFunctional

((*, Integer) → *) → Array → Array
λcurried function
Parameters
  • function(unnamed)

    The function to apply to each (element, index) pair

  • Array(unnamed)

    The array to iterate over

  • Returns:Array

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']

matchesRegexBoolean

RegExp → * → Boolean
λcurried function
Parameters
  • RegExpre

    the regexp to use to test

  • Anyvalue

    the value to test

  • Returns:Boolean

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

negateFunctional

(a → Boolean) → (a → Boolean)
Parameters
  • function(unnamed)

    A function that takes one input and returns a Boolean

  • Returns:function

    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')"

neighborsPassBoolean

((a, a) → Boolean) → Array → Boolean
λcurried function
Parameters
  • functioncheckFn

    2-input function that returns true if the inputs pass check, false otherwise

  • Arrayarray

    Array or other iterable with elements to check

  • Returns:Boolean

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

NonBlankStrModelModel

* → String | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:String

    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'

NonNegativeIntModelModel

* → * | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:Integer

    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)'

NonNegativeNumModelModel

* → * | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:Number

    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)'

NothingADT

() → Nothing
Parameters
  • Returns:Maybe

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'

nowConversion

() → Date
Parameters
  • Returns: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

NumberModelModel

* → Number | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:Number

    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'

NumZeroToOneModelModel

* → Number | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:Number

    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"'

NumZeroToOneXModelModel

* → Number | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:Number

    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"'

objBadKeyValidation

Model → Object → String | undefined
λcurried function
Parameters
  • ModelkeyModel

    The Model to check keys against

  • Returns:String
    • The bad key if found, undefined otherwise

Iterates 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})  //=> ' '

objBadValValidation

Model → Object → [k, v] | undefined
λcurried function
Parameters
  • ModelvalueModel

    The Model to check values against

  • Returns:Array
    • The key/value pair for the bad value, or undefined if all values valid

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', ' ']

ObjectModelModel

* → Object | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:Number

    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"'

objHasKeyBoolean

String → a → Boolean
λcurried function
Parameters
  • stringkey

    The key to check for

  • Anyx

    The value to test

  • Returns:Boolean

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

OkADT

a → Ok a
Parameters
  • Any(unnamed)

    The value to wrap in an Ok

  • Returns:Result

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'

omitFunctional

[ String ] → Object → Object
λcurried function
Parameters
  • Array.<string>(unnamed)

    A list of keys to omit

  • Object(unnamed)

    An object to process

  • Returns:Object

    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'}

orFunctional

(a → Boolean | Pred a) → (a → Boolean | Pred a) → a → Boolean
λcurried function
Parameters
  • function(unnamed)

    First function that returns a Boolean

  • function(unnamed)

    Second function that returns a Boolean

  • Returns:function

    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

PairADT

(a, b) → Pair a b
Parameters
  • Any(unnamed)

    The first (left) value to wrap in a Pair

  • Any(unnamed)

    The second (right) value to wrap in a Pair

  • Returns: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'

parseUTCStrConversion

String → Date
Parameters
  • StringutcString

    The UTC timestamp to convert

  • Returns:Date

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

passesModelCheckBoolean

Model → * → Boolean
λcurried function
Parameters
  • ModelModel

    The Model to test against

  • Anyinput

    The value to test

  • Returns:Boolean

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

passesObjKeyCheckBoolean

Model → * → Boolean
λcurried function
Parameters
  • ModelkeyModel

    the Model to check keys against

  • Anyobj

    The item to check

  • Returns:Boolean

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 object
  • false if the input IS a Javascript object AND has a key (property name) that violates specified Model

Intended 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

passesObjValCheckBoolean

Model → * → Boolean
λcurried function
Parameters
  • ModelvalueModel

    the Model to check values against

  • Anyobj

    The item to check

  • Returns:Boolean

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 object
  • false if the input IS a Javascript object AND has a value that violates specified Model

Intended 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

pickFunctional

[String] → Object → Object
λcurried function
Parameters
  • Array.<String>(unnamed)

    A list of keys to include

  • Object(unnamed)

    The object to copy from

  • Returns:Object

    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'}

pipeFunctional

((a → b), …, (y → z)) → a → z
λcurried function
Parameters
  • function(unnamed)

    Two or more curried functions to compose in left-to-right order

  • Returns:function

    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'

pipeChainableFunctional

Chain m => ((a → m b), …, (y → m z)) → a → m z
λcurried function
Parameters
  • Any(unnamed)

    Two or more chainable operations

  • Returns:ADT

    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

PositiveFracStrModelModel

* → * | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:Number

    The validated input

An ObjectModel which validates that an input is:

  • A Javascript String
  • Is in the form 'x' or 'x/y' where x and y are positive integers

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")'

PositiveIntModelModel

* → * | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:Number

    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)'

PositiveNumModelModel

* → * | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:Number

    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)'

redactConversion

(a, [b], c) → a
Parameters
  • Anyvalue

    The value to redact

  • Array.<RegExp>addlPatterns

    Any additional patters to test keys against

  • stringparentKey

    the key that value was stored under, if any

  • Returns:*

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:

  • Strings longer than 10 characters are replaced by '[REDACTED ...' + last 4 chars + ']'
  • Strings 10 characters long or less are replaced by '[REDACTED]'

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]"}'

REDACT_PATTERNSConstant

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

reFromTemplateConversion

[string], …stringsAndOrRegExps → RegExp | EXCEPTION
Parameters
  • Returns:RegExp

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

resultToPOJOConversion

Result [e] a → Object
Parameters
  • Resultresult

    The Crocks Result instance to convert

  • Returns:Object

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": [
                                     //                {}
                                     //              ]
                                     //            }`

resultUnwrapConversion

Result e a → e | a
Parameters
  • Anyx

    The Crocks Result instance to unwrap

  • Returns:Any

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

RE_BASE58_CHARConstant

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

RE_RATIONALConstant

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'

RE_UTC_TIMESTAMPConstant

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

RE_UUIDConstant

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

RE_UUID_LOWER_CASEConstant

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

RE_UUID_UPPER_CASEConstant

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

satisfiesBetweenBoundsBoolean

a → Boolean → ((a, a) → Integer) → a → Boolean
λcurried function
Parameters
  • AnylowerBound

    the lower bound to be satisfied

  • AnyupperBound

    the upper bound to be satisfied

  • BooleanlowerInclusive

    if true, then value is allowed equal lowerBound

  • BooleanupperInclusive

    if true, then value is allowed equal upperBound

  • functioncomparatorFn

    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.

  • Anyvalue

    The item to check against lowerBound and upperBound

  • Returns:Boolean

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

satisfiesLowerBoundBoolean

a → Boolean → ((a, a) → Integer) → a → Boolean
λcurried function
Parameters
  • AnylowerBound

    the lower bound to be satisfied

  • Booleaninclusive

    if true, then value is allowed equal lowerBound

  • functioncomparatorFn

    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.

  • Anyvalue

    The item to check against lowerBound

  • Returns:Boolean

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

satisfiesUpperBoundBoolean

a → Boolean → ((a, a) → Integer) → a → Boolean
λcurried function
Parameters
  • AnyupperBound

    the upper bound to be satisfied

  • Booleaninclusive

    if true, then value is allowed equal upperBound

  • functioncomparatorFn

    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.

  • Anyvalue

    The item to check against upperBound

  • Returns:Boolean

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

setArityFunctional

Number → ((*) → a) → (*) → a
λcurried function
Parameters
  • number(unnamed)

    arity - Number of arguments for the returned function to accept

  • function(unnamed)

    The function to convert

  • Returns:function

    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

setPathFunctional

Idx = String | Int | Symbol => [Idx] → * → Object → Object
λcurried function
Parameters
  • ArraypathArray

    the path to set, expressed as an array

  • Anyvalue

    the value to store at path

  • Objectobject

    the original object

  • Returns: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"

StringModelModel

* → String | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:String

    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'

sysLocaleDatetime

() → String
Parameters
  • Returns: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'

sysTimezoneDatetime

() → String
Parameters
  • Returns:String

Returns Datetime zone string from current environment

const sysTimezone = require('@eluvio/elv-js-helpers/Datetime/sysTimezone')

sysTimezone() //=> 'America/Los_Angeles'

TFunctional

{} → a
Parameters
  • Returns:Boolean

    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

throwErrorMisc

String → THROW
Parameters
  • Stringmessage

    Error message for exception

  • Returns:Nothing

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'

throwIfArgsBadValidation

ObjectOrModel → * → undefined | THROW
λcurried function
Parameters
  • ObjectmodelOrObj

    a Model or an Object that can be used as an ObjectModel spec

  • Anyargs

    the input to validate

  • Returns:Any

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'

throwIfFalseValidation

String → a → a | THROW
λcurried function
Parameters
  • Stringmessage

    the error message to use in the exception

  • Anyvalue

    the value to check for falsiness

  • Returns:Any

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', [])                                                                  //=> []

throwIfTrueValidation

String → a → a | THROW
λcurried function
Parameters
  • Stringmessage

    the error message to use in the exception

  • Anyvalue

    the value to check for truthiness

  • Returns:Any

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

throwIfUndefinedValidation

String → a → a | THROW
λcurried function
Parameters
  • Stringmessage

    the error message to use in the exception

  • Anyvalue

    the value to check if undefined

  • Returns:Any

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"

throwsExceptionBoolean

a → Boolean
Parameters
  • functionfn

    The function to test

  • Returns:Boolean

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

timesFunctional

(Number → a) → Number → [a]
λcurried function
Parameters
  • functionfn

    the function to call with index

  • integerrepeatCount

    the number of times to call the function

  • Returns:Array

    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]

toLocaleStringDatetime

(String | [String], Object) → (Date → String)
λcurried function
Parameters
  • Stringlocales

    The locales argument to pass to Date.toLocaleString()

  • Objectoptions

    The options argument to pass to Date.toLocaleString()

  • Returns:function

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'

toPairsConversion

Object → List (Pair String a)
Parameters
  • Object(unnamed)

    The object to convert

  • Returns:List

    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 ) ]'

truthTableFunctional

[*] → [Boolean] → *
λcurried function
Parameters
  • ArraychoiceArray

    An array of items to choose from

  • Array.<Boolean>boolArray

    An array of booleans used to determine which element to return from choiceArray

  • Returns:Any

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'
  }
}

tryCatchFunctional

((*) → b) → (*) → Result e b
λcurried function
Parameters
  • functionfn

    The function to convert

  • Returns:Result

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']

uniqFunctional

[*] → [*]
Parameters
  • Array(unnamed)

    the array of elements

  • Returns:Array

    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)                          //=> []

UTCStrModelModel

* → String | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:String

    The validated input

An ObjectModel which validates that an input is:

  • A Javascript String
  • In UTC timestamp format e.g. '2022-01-01T14:00:00Z'
  • A valid Datetime

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'

utcStrToDateDatetime

String → Date
Parameters
  • StringutcString

    The UTC timestamp to convert

  • Returns:Date

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'

uuidFunctional

() → a
Parameters
  • Returns:string

    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

UUIDStrLowerModelModel

* → String | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:String

    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")`

UUIDStrModelModel

* → String | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:String

    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'

UUIDStrUpperModelModel

* → String | THROW
Parameters
  • Any(unnamed)

    The input to validate

  • Returns:String

    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")`

validateWithModelValidation

Model → (a → Result [String] a)
λcurried function
Parameters
  • ModelModel

    An ObjectModel definition to validate against

  • Anyinput

    The input to validate

  • Returns:function

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

wrapNonArrayConversion

Non-array n => n | [a] → [n] | [a]
Parameters
  • Anyx

    The value to wrap in an array (if it is not already an array)

  • Returns: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]

_boundBetweenErrMsgMisc

a → a → Boolean → Boolean → String
Parameters
  • AnylowerBound
  • AnyupperBound
  • BooleanlowerInclusive

    Whether values are allowed to equal lowerBound

  • BooleanupperInclusive

    Whether values are allowed to equal upperBound

  • Returns:String

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'

_boundLowerErrMsgMisc

a → Boolean → String
Parameters
  • AnylowerBound
  • Booleaninclusive

    Whether values are allowed to equal lowerBound

  • Returns:String

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'

_boundUpperErrMsgMisc

a → Boolean → String
Parameters
  • AnyupperBound
  • Booleaninclusive

    Whether values are allowed to equal upperBound

  • Returns:String

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'

_objBadKeyErrMsgModelAssertion

Model → ((Boolean, String) → String)
Parameters
  • ModelkeyModel

    The Model to check keys against

  • Returns:function

    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)'

_objBadValErrMsgModelAssertion

Model → ((Boolean, String) → String)
Parameters
  • ModelvalueModel

    The Model to check values against

  • Returns:function

    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: "  "))'

_strOrRegExSrcConversion

a → String | EXCEPTION
Parameters
  • Anyx

    The value to inspect

  • Returns:String

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)'

_throwIfNotErrValidation

Err a | b → Err a | THROW
Parameters
  • Anyx

    the value to check

  • Returns:Err

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'))

_throwIfNotResultValidation

Result a | b → Result a | THROW
Parameters
  • Anyx

    the value to check

  • Returns:Result

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'

_typeWithOkErrValidation

a → Boolean
Parameters
  • Returns: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"