@eluvio/elv-js-helpers
Version:
A collection of Javascript helper functions used by several Eluvio libraries.
79 lines (75 loc) • 3.34 kB
JavaScript
'use strict'
const assertionErrMsg = require('./assertionErrMsg')
const conditionalCheck = require('../Boolean/conditionalCheck')
const isFunction = require('../Boolean/isFunction')
/**
* Returns a 2-element array for use in an [ObjectModel assertion](http://objectmodel.js.org/#doc-assertions)
*
* 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.
*
* @function
* @category ModelAssertion
* @sig ((Boolean, *, String) -> String) ObjectModelErrMsgFn => Model -> (a -> Boolean) -> String -> [(* -> Boolean), ObjectModelErrMsgFn | String]
* @param {Function} preCheckFn - The preliminary check that must pass in order for `assertFn` to be checked.
* @param {Function} assertFn - The assertion to check.
* @param {(String|Function)} msgStrOrFn - 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.
* @example
*
* 'use strict'
* const passesModelCheck = require('@eluvio/elv-js-helpers/Boolean/passesModelCheck')
*
* const NumberModel = require('@eluvio/elv-js-helpers/Model/NumberModel')
*
* const assertAfterCheck = require('@eluvio/elv-js-helpers/ModelAssertion/assertAfterCheck')
*
* const IntegerModel = NumberModel
* .extend()
* .assert(
* ...assertAfterCheck(
* passesModelCheck(NumberModel),
* n => Number.isInteger(n),
* 'must be an integer'
* )
* )
* .as('Integer')
*
* IntegerModel(42) //=> 42
*
* IntegerModel(4.2) //=> EXCEPTION: 'Value must be an integer (got: 4.2)'
*
* IntegerModel('foo') //=> EXCEPTION: 'expecting Number, got String "foo"'
*
* // Compare vs. case where assertAfterCheck is not used:
*
* const assertionErrMsg = require('@eluvio/elv-js-helpers/ModelAssertion/assertionErrMsg')
*
* const IntegerModelNoPrecheck = NumberModel
* .extend()
* .assert(
* n => Number.isInteger(n),
* assertionErrMsg('must be an integer')
* )
* .as('Integer')
*
* IntegerModelNoPrecheck('foo') //=> EXCEPTION: 'expecting Number, got String "foo"\nValue must be an integer (got: "foo")'
*
*/
const assertAfterCheck = (preCheckFn, assertFn, msgStrOrFn) =>
[
conditionalCheck(preCheckFn, assertFn),
isFunction(msgStrOrFn) ? msgStrOrFn : assertionErrMsg(msgStrOrFn)
]
module.exports = assertAfterCheck