UNPKG

ramda-extension

Version:

Helpful functions built on top of the mighty Ramda

2,254 lines (2,016 loc) 95.3 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('ramda')) : typeof define === 'function' && define.amd ? define(['exports', 'ramda'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.R_ = {}, global.R)); }(this, (function (exports, ramda) { 'use strict'; /** * Returns true if argument equals to 0. * * @func * @category Relation * * @param {any} value * @return {boolean} True if `value` is 0 * * @example * * R_.equalsToZero(3) // false * R_.equalsToZero(0) // true * R_.equalsToZero(-3) // false * * @sig a -> Boolean */ var equalsToZero = ramda.equals(0); var emptyString = ''; var emptyArray = []; var emptyObject = {}; /** * Testing if argument equals to '' * * @func * @category Relation * * @param {any} value * @return {boolean} True if `value` is empty string * * @example * * R_.equalsToEmptyString('') // true * R_.equalsToEmptyString('hi') // false * * @sig a -> Boolean */ var equalsToEmptyString = ramda.equals(emptyString); /** * Returns true if argument is neither null or undefined. * * @func * @category Logic * * @example * * R_.isNotNil(null) // false * R_.isNotNil(undefined) // false * R_.isNotNil('') // true * R_.isNotNil(false) // true * R_.isNotNil(0) // true * R_.isNotNil([]) // true * R_.isNotNil({}) // true * * @sig a -> Boolean */ var isNotNil = ramda.complement(ramda.isNil); /** * Alias for `isNotNil` * * @deprecated * @func * @category Logic * @see isNotNil * * @example * * R_.notNil(null) // false * R_.notNil(undefined) // false * R_.notNil('') // true * R_.notNil(false) // true * R_.notNil(0) // true * R_.notNil([]) // true * R_.notNil({}) // true * * @sig a -> Boolean */ var notNil = isNotNil; /** * Returns true if the given value is not its type's empty value * * @func * @category Logic * * @sig a -> Boolean * * @example * * R_.isNotEmpty([1, 2, 3]); // true * R_.isNotEmpty([]); // false * R_.isNotEmpty(''); // false * R_.isNotEmpty(null); // true * R_.isNotEmpty({}); // false * R_.isNotEmpty({length: 0}); // true * */ var isNotEmpty = ramda.complement(ramda.isEmpty); /** * Alias for `isNotEmpty` * * @deprecated * @func * @category Logic * @see isNotEmpty * * @example * * R_.notEmpty([1, 2, 3]); // true * R_.notEmpty([]); // false * R_.notEmpty(''); // false * R_.notEmpty(null); // true * R_.notEmpty({}); // false * R_.notEmpty({length: 0}); // true * * @sig a -> Boolean */ var notEmpty = isNotEmpty; /* eslint-disable max-len */ /** * Return negation of native isNaN function. * * @func * @category Logic * * @example * * R_.isNotNaN(0) // true * R_.isNotNaN('') // true * R_.isNotNaN([]) // true * R_.isNotNaN(null) // true * R_.isNotNaN({}) // false * R_.isNotNaN(NaN) // false * R_.isNotNaN(undefined) // false * * @see http://stackoverflow.com/questions/9716468/is-there-any-function-like-isnumeric-in-javascript-to-validate-numbers * * @sig a -> Boolean */ var isNotNaN = ramda.complement(isNaN); /* eslint-enable max-len */ /** * Alias for `isNotNaN`. * * @deprecated [description] * @func * @category Logic * @see isNotNaN * * @example * * R_.notNaN(0) // true * R_.notNaN('') // true * R_.notNaN([]) // true * R_.notNaN(null) // true * R_.notNaN({}) // false * R_.notNaN(NaN) // false * R_.notNaN(undefined) // false * * @sig a -> Boolean */ var notNaN = isNotNaN; /** * Returns true if argument is finite numeric value. * * @func * @category Logic * * @example * * R_.isNumeric(-1) // true * R_.isNumeric(0) // true * R_.isNumeric(1) // true * R_.isNumeric(1.1) // true * R_.isNumeric(Infinity) // false * R_.isNumeric(NaN) // false * R_.isNumeric('') // false * R_.isNumeric(() => {}) // false * R_.isNumeric(false) // false * R_.isNumeric(null) // false * R_.isNumeric(undefined) // false * R_.isNumeric({}) // false * R_.isNumeric([]) // false * * @sig a -> Boolean * */ var isNumeric = ramda.allPass([ramda.o(notNaN, parseFloat), isFinite]); /** * Returns true if argument is not finite numeric value. * * @func * @category Logic * * @example * * R_.isNotNumeric(-1) // false * R_.isNotNumeric(0) // false * R_.isNotNumeric(1) // false * R_.isNotNumeric(1.1) // false * R_.isNotNumeric(Infinity) // true * R_.isNotNumeric(NaN) // true * R_.isNotNumeric('') // true * R_.isNotNumeric(() => {}) // true * R_.isNotNumeric(false) // true * R_.isNotNumeric(null) // true * R_.isNotNumeric(undefined)// true * R_.isNotNumeric({}) // true * R_.isNotNumeric([]) // true * * @sig a -> Boolean * */ var isNotNumeric = ramda.complement(isNumeric); /** * Alias for `isNotNumeric`. * * @deprecated * @func * @category Logic * @see isNotNumeric * * @example * * R_.notNumeric(-1) // false * R_.notNumeric(0) // false * R_.notNumeric(1) // false * R_.notNumeric(1.1) // false * R_.notNumeric(Infinity) // true * R_.notNumeric(NaN) // true * R_.notNumeric('') // true * R_.notNumeric(() => {}) // true * R_.notNumeric(false) // true * R_.notNumeric(null) // true * R_.notNumeric(undefined)// true * R_.notNumeric({}) // true * R_.notNumeric([]) // true * * @sig a -> Boolean * */ var notNumeric = isNotNumeric; /** * Always returns null. * * @func * @category Function * * @example * * R_.alwaysNull() // null * * @sig a -> Object */ var alwaysNull = ramda.always(null); /** * Always returns empty string. * * @func * @category Function * * @example * * R_.alwaysEmptyString() // '' * * @sig a -> String */ var alwaysEmptyString = ramda.always(emptyString); /** * Returns a function that creates new instances of whatever argument * is passed in each time it's called. * * @func * @private * @example * * const alwaysNewArray = alwaysNew([]); * const a = alwaysNewArray(); * const b = alwaysNewArray(); * // a !== b * */ var alwaysNew = ramda.thunkify(ramda.clone); /** * Always returns a new empty array. * * @func * @category Function * * @example * * R_.alwaysEmptyArray() // [] * * @sig a -> Array */ var alwaysEmptyArray = alwaysNew(emptyArray); /** * Always returns zero. * * @func * @category Function * * @example * * R_.alwaysZero() // 0 * * @sig * -> Number */ var alwaysZero = ramda.always(0); /** * Always returns number one. * * @func * @category Function * * @example * * R_.alwaysOne() // 1 * * @sig * -> Number */ var alwaysOne = ramda.always(1); /** * Always returns a new empty object. * * @func * @category Function * * @example * * R_.alwaysEmptyObject() // {} * * @sig a -> Object */ var alwaysEmptyObject = alwaysNew(emptyObject); /** * Applies composition by a list of functions. * * @func * @category Function * * @example * * R_.applyCompose([multiply(2), add(1)])(3) // 8 * * @sig [(a -> b)] -> a -> b */ var applyCompose = ramda.apply(ramda.compose); /** * Applies pipe by to a list of functions. * * @func * @category Function * * @example * * R_.applyPipe([multiply(2), add(1)])(3) // 7 * * @sig [(a -> b)] -> a -> b */ var applyPipe = ramda.apply(ramda.pipe); /** * See if an number (`val`) is within an array of two numbers ('list'). * * @func * @category Type * @param {Number} a Starting value * @param {Number} b Ending value * @param {Number} val The value to test * @return {Boolean} * @example * * R_.between(1, 5, 4); //=> true * R_.between(3, 8, 2.1); //=> false * R_.between(100.1, 102, 100.1); //=> true */ var between = ramda.curry(function (min, max, val) { if (val >= min && val <= max) { return true; } return false; }); /** * Returns true if argument is type of Array. * * @func * @category Type * * @example * * R_.isArray([]) // true * R_.isArray('') // false * @sig a -> Boolean */ var isArray = ramda.is(Array); /** * Returns true if argument is type of Function. * * @func * @category Type * * @example * * R_.isFunction(() => {}) // true * R_.isFunction({}) // false * R_.isFunction([]) // false * R_.isFunction('') // false * R_.isFunction(0) // false * * @sig a -> Boolean * */ var isFunction = ramda.is(Function); /** * Returns true if argument is type of Object. * * @func * @category Type * * @example * * R_.isObject({}) // true * R_.isObject([]) // true * R_.isObject('') // false * @sig a -> Boolean */ var isObject = ramda.is(Object); /** * Returns true if argument is lower than 0. * * @func * @category Math * * @example * * R_.isNegative(3) // false * R_.isNegative(0) // false * R_.isNegative(-3) // true * * @sig Number -> Boolean */ var isNegative = ramda.gt(0); /** * Alias for `equalsToEmptyString`. * * @deprecated * @func * @category String * @example * * R_.equalsEmptyString('') // true * R_.equalsEmptyString('hi') // false * * @see equalsToEmptyString * @sig a -> Boolean */ var equalsEmptyString = equalsToEmptyString; /** * Returns true if argument is null, undefined or ''. * * @func * @category Logic * * @example * * R_.isNilOrEmptyString(null) // true * R_.isNilOrEmptyString(undefined)// true * R_.isNilOrEmptyString('') // true * R_.isNilOrEmptyString(false) // false * R_.isNilOrEmptyString(0) // false * R_.isNilOrEmptyString([]) // false * R_.isNilOrEmptyString({}) // false * * @sig a -> Boolean */ var isNilOrEmptyString = ramda.anyPass([ramda.isNil, equalsEmptyString]); /** * Returns true if argument is not nil object. * * @func * @category Logic * * @example * * R_.isNotNilObject({}) // true * R_.isNotNilObject([]) // true * R_.isNotNilObject(() => {}) // true * R_.isNotNilObject(null) // false * R_.isNotNilObject() // false * R_.isNotNilObject(1) // false * R_.isNotNilObject("") // false * * @sig a -> Boolean * */ var isNotNilObject = ramda.allPass([notNil, isObject]); /** * Returns true if argument is RegExp. * * @func * @category Type * * @example * * R_.isRegExp(/foo/) // true * R_.isRegExp(0) // false * * @sig a -> Boolean * */ var isRegExp = ramda.is(RegExp); /** * Returns true if argument is not RegExp. * * @func * @category Type * * @example * * R_.isNotRegExp(/foo/) // false * R_.isNotRegExp(0) // true * * @sig a -> Boolean * */ var isNotRegExp = ramda.complement(isRegExp); /** * Returns true if argument is greater than 0. * * @func * @category Math * * @example * * R_.isPositive(3) // true * R_.isPositive(0) // false * R_.isPositive(-3) // false * * @sig Number -> Boolean */ var isPositive = ramda.lt(0); /** * Returns true if argument is Promise. * * @func * @category Type * * @example * * R_.isPromise(Promise.resolve()) // true * R_.isPromise(0) // false * * @sig a -> Boolean * */ var isPromise = ramda.allPass([isObject, ramda.o(isFunction, ramda.prop('then'))]); /** * Returns true if argument is type of String. * * @func * @category Type * * @example * * R_.isString({}) // false * R_.isString([]) // false * R_.isString('') // true * * @sig a -> Boolean */ var isString = ramda.is(String); /** * Alias for Boolean constructor. Returns 'true' for truthy values. * * @func * @category Logic * * @param {any} input * @return {Boolean} `true` if `input` is truthy * * @example * * R_.isTruthy(true) // true * R_.isTruthy({}) // true * R_.isTruthy([]) // true * R_.isTruthy(1) // true * R_.isTruthy("hello") // true * R_.isTruthy(false) // false * R_.isTruthy(0) // false * R_.isTruthy("") // false * * @sig a -> Boolean */ var isTruthy = Boolean; /** * Returns `true` for falsy values. Complement of `R_.falsy`. * * @func * @category Logic * * @param {any} input * @return {Boolean} `true` if `input` is falsy * * @example * * R_.isFalsy(true) // false * R_.isFalsy({}) // false * R_.isFalsy([]) // false * R_.isFalsy(1) // false * R_.isFalsy("hello") // false * R_.isFalsy(false) // true * R_.isFalsy(0) // true * R_.isFalsy("") // true * * @sig a -> Boolean */ var isFalsy = ramda.complement(isTruthy); /** * Returns true if the argument is an instance of Error. * * @func * @category Type * * @example * * R_.isError(new Error()) // true * R_.isError(null) // false * * @sig a -> Boolean * */ var isError = ramda.is(Error); /** * Function with side-effect. Logs input to console and returns that input. Should be used only in development. * * @func * @category Debugging * * @example * * R_.log('hello') // logs 'hello' * compose(R_.log, R.sum)([1, 3]) // logs 4 * * @sig a -> a * */ var log = ramda.tap(function (x) { return console.log(x); }); /** * Function with side-effect. Logs input to console and returns that input. * Similar to "log" but allows to label logged value. Should be used only in development. * * @func * @category Debugging * * @sig a -> b -> b * * @example * * compose(calculation2, R_.trace('Page A'), calculation1); // logs "Page A" and result of calculation1 * */ var trace = ramda.useWith(ramda.tap, [ramda.curryN(2, console.log), ramda.identity]); /** * Call function passed as first argument with arguments determined by second parameter in order. * * @func * @category Function * * @sig (a → ... → b) → [a, ..., b] → c * * @example * * const f = (a) => (b) => a + b * * R_.reduceCallable(f, [1, 2]) // 3 * */ var reduceCallable = ramda.reduce(ramda.call); /** * Takes first argument from the arguments * * @func * @category Function * * @example * * R_.headArg('a', 'b', 'c') // a * * */ var headArg = ramda.nthArg(0); /** * Extends the reduce functionality by adding the original accumulator value * as a third argument and the original list as a fourth argument to the * iterator function. * * @func * @category List * * @param {Function} fn The iterator function. Receives four arguments, the * accumulator, the current element, the source accumulator and the * source list. * @param {*} acc The initial accumulator value and value passed as the source * accumulator value in the iterator function. * @param {Array} list The list to iterator over and value passed as the source * list in the iterator function. * @return {*} The reduced result. * * @example * R_.reduceSource((acc, v, sAcc) => v + acc + sAcc, 1, [1, 2, 3]); // 10 * R_.reduceSource(R.pipe(R.unapply(R.flatten), R.sum), 0, [1, 2]); // 9 * * @sig ((a, b, a, [b]) -> a) -> a -> [b] -> a */ var reduceSource = ramda.converge(ramda.reduce, [ramda.converge(ramda.partialRight, [headArg, // iteratorFn ramda.unapply(ramda.tail) // [accumulator, list] ]), ramda.nthArg(1), // accumulator ramda.nthArg(2) // list ]); /** * Returns first not nil value * * @func * @category List * * @example * * R_.findNotNil([null, undefined, 0, true]) // 0 * * @sig [a] -> a * */ var findNotNil = ramda.find(notNil); /** * Creates pairs from value and list of values. * Value is always prepended to the pair. * * @func * @category List * @see xPairsRight * * @example * * R_.xPairs(1, [2, 3]) // [[1, 2], [1, 3]] * * @sig a -> [b] -> [[a, b]] */ var xPairs = ramda.useWith(ramda.xprod, [ramda.of(Array), ramda.identity]); var getPredicates = ramda.compose(ramda.map(ramda.juxt([applyCompose, ramda.last])), xPairs); /** * Returns first result from evaluation of functions in the list, that satisfies predicate. * Returns `undefined` otherwise. * * @func * @category Function * @see dispatch * * @param {function} predicate Predicate that is applied to result of calling fn from `listFns` with `values` * @param {array} listFns List of functions * @param {*} values Values applied to functions from `listFns` * @return {any} Returns first result of calling fn from `listFns` with `values` that satisfies `predicate`. * * @example * * const firstTruthy = R_.dispatchWith(Boolean)([ * prop("foo"), * prop("bar"), * ]) * * firstTruthy({foo: "foo", bar: false}) // "foo" * firstTruthy({foo: false, bar: "bar" }) // "bar" * * @sig [a] -> b|undefined */ var dispatchWith = ramda.converge(ramda.call(ramda.cond), [getPredicates]); /** * Returns first not nil result from evaluation of functions in the list. * Returns `undefined` otherwise. * * @func * @category Function * @see dispatchWith * * @param {array} listFns List of functions * @param {*} values Values applied to functions from `listFns` * @return {any} Returns first not nil result of calling fn from `listFns` with `values`. * * @example * * const validateName = R_.dispatch([ * ifElse(Boolean, R_.noop, always('Name is required.')), * ifElse(R_.isString, R_.noop, always('Name must be valid.')), * ]); * * validateName("") // 'Name is required.' * validateName(111) // 'Name must be valid.' * validateName("Valid name") // undefined * * @sig [a] -> b|undefined */ var dispatch = dispatchWith(notNil); /** * Alias for `alwaysNull` * * @func * @category Function * * @sig a -> Object * * @example * * R_.noop() // null * */ var noop = alwaysNull; /** * Constructs RegExp. * * @func * @category Function * * @example * * test(R_.constructRegExp('end$', 'gi'), 'in the end') // true * */ var constructRegExp = ramda.constructN(2, RegExp); var getRegExp_$1 = ramda.useWith(ramda.flip(constructRegExp)('gi'), [ramda.concat('^')]); /** * Testing string if starts with some prefix. * * @func * @category String * * @param {string} prefix * @param {string} x * @return {boolean} True if `x` starts with `prefix` * * @example * * R_.startsWithPrefix('h', 'hello') // true * R_.startsWithPrefix('hell', 'hello') // true * R_.startsWithPrefix('h', 'good bye') // false * * @sig a -> b -> Boolean */ var startsWithPrefix = ramda.useWith(ramda.test, [getRegExp_$1, ramda.identity]); /** * Testing string if starts with some prefix ignoring case. * * @func * @category String * * @param {string} prefix * @param {string} x * @return {boolean} True if `x` starts with `prefix` ignore case * * @example * * R_.startsWithPrefixIgnoreCase('h', 'HELLO') // true * R_.startsWithPrefixIgnoreCase('HELL', 'hello') // true * R_.startsWithPrefixIgnoreCase('hello', 'hello') // true * R_.startsWithPrefixIgnoreCase('h', 'good bye') // false * * @sig a -> b -> Boolean */ var startsWithPrefixIgnoreCase = ramda.useWith(ramda.startsWith, [ramda.toUpper, ramda.toUpper]); var getRegExp_ = ramda.useWith(ramda.flip(constructRegExp)('gi'), [ramda.flip(ramda.concat)('$')]); /** * Testing string if ends with some suffix. * * @func * @category String * * @param {string} suffix * @param {string} x * @return {boolean} True if `x` ends with `suffix` * * @example * * R_.endsWithSuffix('o', 'hello') // true * R_.endsWithSuffix('ello', 'hello') // true * R_.endsWithSuffix('y', 'good bye') // false * * @sig a -> b -> Boolean */ var endsWithSuffix = ramda.useWith(ramda.test, [getRegExp_, ramda.identity]); /** * Testing string if ends with some suffix ignoring case. * * @func * @category String * * @param {string} suffix * @param {string} x * @return {boolean} True if `x` ends with `suffix` ignore case * * @example * * R_.endsWithSuffixIgnoreCase('o', 'HELLO') // true * R_.endsWithSuffixIgnoreCase('ELLO', 'hello') // true * R_.endsWithSuffixIgnoreCase('hello', 'hello') // true * R_.endsWithSuffixIgnoreCase('o', 'good bye') // false * * @sig a -> b -> Boolean */ var endsWithSuffixIgnoreCase = ramda.useWith(ramda.endsWith, [ramda.toUpper, ramda.toUpper]); /** * Converts arguments to list. * * @func * @category Function * * @example * * R.compose(R.sum, R_.argumentsToList)(1, 2, 3) // 6 * * @sig (a, b, c, ...) → ([a, b, c, ...]) */ var argumentsToList = ramda.unapply(ramda.identity); /** * Resolves to true if all elements in first list are found within the second list * * @func * @category List * * * @param {Array} List * @param {Array} List * @return {Boolean} If all items from first array are in the second array. * * @example * * R_.containsAll(['a', 'b'], ['a', 'b', 'c']) // true * R_.containsAll(['a', 'b', 'd'], ['a', 'b', 'c']) // false * * @sig [a] -> [a] -> Boolean * */ var containsAll = ramda.curry(ramda.compose(ramda.isEmpty, ramda.difference)); /** * Returns `true` if any of the items from first array are in the second array. * * @func * @category List * * @param {Array} List * @param {Array} List * @return {Boolean} If any of the items from first array are in the second array. * * @example * * R_.containsAny(['a', 'e'], ['a', 'b', 'c']) // true * R_.containsAny(['e', 'f'], ['a', 'b', 'c']) // false * * @sig [a] -> [a] -> Boolean * */ var containsAny = ramda.curry(ramda.compose(ramda.not, ramda.isEmpty, ramda.intersection)); /** * Returns `true` if any of the items from first array is not the second array. * * @func * @category List * * @param {Array} List * @param {Array} List * @return {Boolean} If any of the items from first array is not in the second array. * * @example * * R_.containsNone(['e', 'f'], ['a', 'b', 'c']) // true * R_.containsNone(['a', 'f'], ['a', 'b', 'c']) // false * * @sig [a] -> [a] -> Boolean */ var containsNone = ramda.curry(ramda.compose(ramda.isEmpty, ramda.intersection)); /** * Splits string by dot into list. * * @func * @category String * * @example * * R_.splitByDot('a.b.c') // ['a', 'b', 'c'] * * @sig String -> [String] */ var splitByDot = ramda.split('.'); /** * Returns deeply merged object by merging all objects in a passed list. Merging is applied from the right. * See mergeDeepRight from Ramda. * * @func * @category Object * * @see mergeDeepLeftAll, mergeDeepAllWith, mergeDeepAllWithKey * @param {array} list Array of objects * @returns {object} Merged object * * @example * * const a = { fooA: { bar: 'a' }, shared: { baz: 1 } }; * const b = { fooB: { bar: 'b' }, shared: { baz: 2 } }; * const c = { fooC: { bar: 'c' }, shared: { baz: 3 } }; * * R_.mergeDeepRightAll([a, b, c]) * // { * // fooA: { bar: 'a' }, * // fooB: { bar: 'b' }, * // fooC: { bar: 'c' }, * // shared: { baz: 3 }, * // } * * @sig [{a}] -> {a} */ var mergeDeepRightAll = ramda.reduce(ramda.mergeDeepRight, {}); /** * Unfolds input object by dot delimetered path inside its keys. * * @func * @category Object * * @example * * R_.unfoldObjectDots({'a.b.c': 1, 'd.e.f': 2, 'g': 3}) * // {a: {b: {c: 1}}, d: {e: {f: 2}}, g: 3} * * @sig Object -> Object */ var unfoldObjectDots = ramda.o(ramda.o(mergeDeepRightAll, ramda.values), ramda.mapObjIndexed(ramda.useWith(ramda.flip(ramda.call), [ramda.identity, ramda.compose(applyCompose, ramda.map(ramda.objOf), splitByDot)]))); var adjustFirstLetter = ramda.o(ramda.join(''), ramda.adjust(0, ramda.toUpper)); /** * Capitalize first letter. * * @func * @category String * * @example * * R_.toUpperFirst('') // '' * R_.toUpperFirst('hello world') // 'Hello world' * * @sig String -> String */ var toUpperFirst = ramda.unless(ramda.isEmpty, adjustFirstLetter); /** * Decapitalize first letter. * * @func * @category String * * @example * * R_.toLowerFirst('HELLO WORLD') // 'hELLO WORLD' * * @sig String -> String */ var toLowerFirst = ramda.o(ramda.join(''), ramda.adjust(0, ramda.toLower)); /** * @private */ var nonAlphaNumericRegExp = constructRegExp('[^a-zA-Z0-9]+', 'g'); /** * Splits string into list. Delimiter is every sequence of non-alphanumerical values. * * @func * @category String * * @example * * R_.splitByNonAlphaNumeric('Hello world/1'); // ['Hello', 'world', '1'] * * @sig String -> [String] * */ var splitByNonAlphaNumeric = ramda.o(ramda.reject(ramda.equals(emptyString)), ramda.split(nonAlphaNumericRegExp)); /** * Converts list of strings to string. * * @func * @category List * * @example * * R_.listToString(['h', 'e', 'l', 'l', 'o']) // 'hello' * * @sig [String] -> String * */ var listToString = ramda.join(emptyString); /** * Converts string into PascalCase. * * @func * @category String * * @example * * R_.toPascalCase('hello-world') // 'HelloWorld' * R_.toPascalCase('hello- world') // 'HelloWorld' * R_.toPascalCase(' hello-/ world/ ') // 'HelloWorld' * * @sig String -> String */ var toPascalCase = ramda.o(listToString, ramda.o(ramda.map(toUpperFirst), splitByNonAlphaNumeric)); /** * Converts string into camelCase. * * @func * @category String * * @example * * R_.toCamelCase('hello-world') // 'helloWorld' * R_.toCamelCase('hello- world') // 'helloWorld' * R_.toCamelCase(' hello-/ world/ ') // 'helloWorld' * * @sig String -> String * */ var toCamelCase = ramda.o(toLowerFirst, toPascalCase); /** * Joins array of string with underscore determiner. * * @func * @category String * * @example * * R_.joinWithUnderscore(['a', 'b', 'c']) // 'a_b_c' * * @sig [String] -> String */ var joinWithUnderscore = ramda.join('_'); /** * Converts string into snake_case. * * @func * @category String * * @example * * R_.toSnakeCase('hello-world') // 'hello_world' * R_.toSnakeCase('hello- world') // 'hello_world' * R_.toSnakeCase(' hello-/ world/ ') // 'hello_world' * * @sig String -> String */ var toSnakeCase = ramda.o(joinWithUnderscore, ramda.o(ramda.map(ramda.toLower), splitByNonAlphaNumeric)); /** * Joins array of string with dash (hyphen) determiner. * * @func * @category String * * @example * * R_.joinWithDash(['a', 'b', 'c']) // 'a-b-c' * * @sig [String] -> String */ var joinWithDash = ramda.join('-'); /** * Converts string into kebab-case. * * @func * @category String * * @example * * R_.toKebabCase('hello-world') // 'hello-world' * R_.toKebabCase('hello- world') // 'hello-world' * R_.toKebabCase(' hello-/ world/ ') // 'hello-world' * * @sig String -> String */ var toKebabCase = ramda.o(joinWithDash, ramda.o(ramda.map(ramda.toLower), splitByNonAlphaNumeric)); /** * Joins array of string with dot determiner. * * @func * @category String * * @example * * R_.joinWithDot(['a', 'b', 'c']) // 'a.b.c' * * @sig [String] -> String */ var joinWithDot = ramda.join('.'); /** * Converts string into dot.case. * * @func * @category String * * @example * * R_.toDotCase('hello-world') // 'hello.world' * R_.toDotCase('hello/*? world') // 'hello.world' * R_.toDotCase(' hello -/ world/ ') // 'hello.world' * * @sig String -> String */ var toDotCase = ramda.o(joinWithDot, ramda.o(ramda.map(ramda.toLower), splitByNonAlphaNumeric)); /** * Converts string into SCREAMING_SNAKE_CASE. * * @func * @category String * * @example * * R_.toScreamingSnakeCase('hello-world') // 'HELLO_WORLD' * R_.toScreamingSnakeCase('hello- world') // 'HELLO_WORLD' * R_.toScreamingSnakeCase(' hello-/ world/ ') // 'HELLO_WORLD' * * @sig String -> String */ var toScreamingSnakeCase = ramda.o(joinWithUnderscore, ramda.o(ramda.map(ramda.toUpper), splitByNonAlphaNumeric)); /** * Filters out every nil value in a list. * * @func * @category List * * @example * * R_.rejectNil([null, undefined, '']); // [''] * * @sig [a] -> [a] * */ var rejectNil = ramda.reject(ramda.isNil); /** * Filters out every value in a list that equals to first argument. * * @func * @category List * * @example * * R_.rejectEq('foo', ['foo', 'bar', 'foo', 'bar']); // ['bar', 'bar'] * * @sig a -> [b] -> [c] * */ var rejectEq = ramda.useWith(ramda.reject, [ramda.equals, ramda.identity]); /** * Joins array of string with space determiner. * * @func * @category String * * @example * * R_.joinWithSpace(['a', 'b', 'c']) // 'a b c' * * @sig [String] -> String */ var joinWithSpace = ramda.join(' '); /** * Returns an over lens to the first index of list. * * @func * @category List * @param {*} v * @param {*} x * @return {*} * @example * * R_.overHead(R.toUpper, ['foo', 'bar', 'baz']); //=> ['FOO', 'bar', 'baz'] * */ var overHead = ramda.over(ramda.lensIndex(0)); /** * Makes a shallow clone of an object, omitting the property at the given dot path. * Note that this copies and flattens * prototype properties onto the new object as well. All non-primitive properties are copied by reference. * * @func * @category Object * * @param {String} path The dot path to the value to omit * @param {Object} obj The object to clone * @return {Object} A new object without the property at path * @example * * R_.dissocDotPath('a.b.c', {a: {b: {c: 42}}}); //=> {a: {b: {}}} */ var dissocDotPath = ramda.curryN(2, ramda.compose(ramda.apply(ramda.dissocPath), overHead(splitByDot), argumentsToList)); /** * Retrieve the value at a given dot path. * * @func * @category Object * @param {String} path The dot path to use. * @param {Object} obj The object to retrieve the nested property from. * @return {*} The data at `path`. * * @example * * R_.dotPath('a.b', {a: {b: 2}}); //=> 2 * R_.dotPath('a.b', {c: {b: 2}}); //=> undefined * */ var dotPath = ramda.useWith(ramda.path, [splitByDot, ramda.identity]); /** * Makes a shallow clone of an object, setting or overriding the nodes required * to create the given path, and placing the specific value at the tail end of * that path. * * @func * @category Object * @param {String} path the dot path to set * @param {*} val The new value * @param {Object} obj The object to clone * @return {Object} A new object equivalent to the original except along the specified path. * @example * * R_.assocDotPath('a.b.c', 42, {a: {b: {c: 0}}}); //=> {a: {b: {c: 42}}} * * // Any missing or non-object keys in path will be overridden * R_.assocDotPath('a.b.c', 42, {a: 5}); //=> {a: {b: {c: 42}}} * * @sig String -> a -> b */ var assocDotPath = ramda.curryN(2, ramda.compose(ramda.apply(ramda.assocPath), overHead(splitByDot), argumentsToList)); /** * Takes last argument from the arguments * * @func * @category Function * * @example * * R_.lastArg('a', 'b', 'c') // c * * */ var lastArg = ramda.nthArg(-1); var resolveDotPath = ramda.converge(dotPath, [headArg, lastArg]); var performMerge = ramda.converge(ramda.call, [ramda.nthArg(1), resolveDotPath, ramda.nthArg(2)]); /** * Merge data in object using custom merge fn. * * @func * @category Object * * @param {String} path The dot path to the value * @param {Function} mergeFn The merging function * @param {*} value Value to merge * @param {Object} obj The object to clone * @return {Object} A new object with merge data * @example * * R_.mergeWithDotPath('a.b', R.mergeRight, { d: 30 }, {a: {b: { c: 20 }}}); //=> {a: {b: { c: 20, d: 30 }}} */ var mergeWithDotPath = ramda.converge(assocDotPath, [headArg, performMerge, lastArg]); /** * Always returns null. * * @func * @category Object * * @example * * R_.mapKeysAndValues(([a, b]) => [b, a], { foo: "bar", baz: "boo" }) * // { bar: "foo", boo: "baz" } * * @sig ([a] -> [b]) -> Object -> Object */ var mapKeysAndValues = ramda.useWith(ramda.compose(ramda.fromPairs, ramda.map), [ramda.identity, ramda.toPairs]); /** * Use map function over the keys of the given object * * @func * @category Object * @param {Function} fn The function to be called on every key of the input object. * @param {Array} obj The object to be iterated over. * @return {Array} The new object with mapped keys. * * @example * * R_.mapKeys(R_.toUpperFirst, {x: 1, y: 2, z: 3}); //=> {X: 2, Y: 4, Z: 6} * */ var mapKeys = ramda.useWith(mapKeysAndValues, [overHead, ramda.identity]); /** * Call apply on function if the function is defined. Otherwise do nothing and return null. * * @func * @category Function * * @param {Function} fn The function which will be called with `args` when defined * @param {Array} args The arguments to call `fn` with * @return {*} result The result, equivalent to `fn(...args)` or null * @example * * const nums = [1, 2, 3]; * R_.applyIfNotNil(R.sum, nums) // 6 * R_.applyIfNotNil(undefined, nums) // null * * @sig (*... -> a) -> [*] -> a */ var applyIfNotNil = ramda.ifElse(notNil, ramda.apply, alwaysNull); /** * @private */ var compareLength = ramda.useWith(ramda.__, [ramda.identity, ramda.length]); /** * Returns true if length of array equals first argument * * @func * @category List * * @example * * const lengthEqualsOne = R_.equalsLength(1) * lengthEqualsOne([{}]) // true * lengthEqualsOne([]) // false * * @sig Number -> [a] -> Boolean */ var equalsLength = compareLength(ramda.equals); /** * Testing string if equals ignoring case. * * @func * @category String * * @param {string} x * @param {string} y * @return {boolean} True if `x` equals `y` ignore case * * @example * * R_.equalsStringIgnoreCase('hello', 'HELLO') // true * R_.equalsStringIgnoreCase('HELLO', 'hello') // true * R_.equalsStringIgnoreCase('hello', 'hello') // true * R_.equalsStringIgnoreCase('hello', 'good bye') // false * * @sig a -> b -> Boolean */ var equalsStringIgnoreCase = ramda.useWith(ramda.equals, [ramda.toLower, ramda.toLower]); /** * Returns true if length of array is smaller or equals than first argument * * @func * @category List * * @example * * const lengthSmallerThanEqualsOne = R_.gteThanLength(1) * lengthSmallerThanEqualsTwo([{},{}]) // false * lengthSmallerThanEqualsTwo([{}]) // true * lengthSmallerThanEqualsTwo([]) // true * * @sig Number -> [a] -> Boolean */ var gteThanLength = compareLength(ramda.gte); /** * Returns true if length of array is smaller than first argument * * @func * @category List * * @example * * const lengthSmallerThanTwo = R_.gtThanLength(2) * lengthSmallerThanTwo([{}]) // true * lengthSmallerThanTwo([{},{}]) // false * * @sig Number -> [a] -> Boolean */ var gtThanLength = compareLength(ramda.gt); /** * Returns true if length of array is bigger or equals than first argument * * @func * @category List * * @example * * const lengthBiggerThanEqualsOne = R_.lteThanLength(1) * lengthBiggerThanEqualsOne([{},{}]) // true * lengthBiggerThanEqualsOne([{}]) // true * lengthBiggerThanEqualsOne([]) // false * * @sig Number -> [a] -> Boolean */ var lteThanLength = compareLength(ramda.lte); /** * Returns true if length of array is bigger than first argument * * @func * @category List * * @example * * const lengthBiggerThanZero = R_.ltThanLength(0) * lengthBiggerThanZero([{}]) // true * lengthBiggerThanZero([]) // false * * @sig Number -> [a] -> Boolean */ var ltThanLength = compareLength(ramda.lt); /** * Applies custom view function on the given lens * * @func * @category Object * @param {Lens} lens * @param {*} v view function * @param {*} x * @return {*} * @example * * R_.viewWith(R.lensIndex(0), R.pathEq(['foo'], 'boo'), [{ foo: 'boo' }]); //=> true * R_.viewWith(R.lensIndex(0), R.divide(R.__, 2), [4]) //=> 2 * */ var viewWith = ramda.useWith(ramda.flip(ramda.o), [ramda.view, ramda.identity, ramda.identity]); /** * Returns true if the given lens equals to given value * * @func * @category Object * @param {Lens} lens * @param {*} v value to equal * @param {*} x * @return {*} * @example * * R_.viewEq(R.lensIndex(0), 'foo', ['foo', 'bar', 'baz']); //=> true */ var viewEq = ramda.useWith(viewWith, [ramda.identity, ramda.equals, ramda.identity]); /** * Applies flatten on array of arguments * * @func * @category List * * @return {Array} flatten array * * @example * * R_.flattenArgs('e', 'f', 'a') // ['e', 'f', 'a'] * R_.flattenArgs('e', ['f', 'a']) // ['e', 'f', 'a'] * R_.flattenArgs('e', ['f', ['a']]) // ['e', 'f', 'a'] * * @sig (a, [b, c]...) -> [a, b, c] */ var flattenArgs = ramda.compose(ramda.flatten, argumentsToList); var recursiveArray = function recursiveArray(r) { return ramda.o(ramda.flatten, ramda.map(flattenValues))(r); }; var recursiveObject = function recursiveObject(r) { return ramda.o(flattenValues, ramda.values)(r); }; /** * Recursively flatten values from object and array. * * @func * @category List * * @param {Array|Object} value * @return {Array} array of values * * @sig {k: v} → [v] * * @example * * R_.flattenValues([ * 'hi', * { foo: 'bar' }, * { * foo: { * bar: ['baz', { foofoo: 'hi' }], * }, * }, * ['bar', 'hi'], * ['barbar', { hrun: 'hi' }], * ]) // ['hi','bar','baz','hi','hi','hi'] * */ var flattenValues = ramda.cond([[isArray, recursiveArray], [isObject, recursiveObject], [ramda.T, ramda.of(Array)]]); /** * Returns true if value is type of Number. * * @func * @category Type * * @param {any} x Value to test * @return {any} True, if value is type of Number * * @example * * R_.isNumber(NaN) // true * R_.isNumber(Infinite) // true * R_.isNumber(1) // true * R_.isNumber(false) // false * R_.isNumber({}) // false * R_.isNumber("1") // false * * @sig a -> Boolean */ var isNumber = ramda.is(Number); var filterFalsy = ramda.filter(ramda.identity); var keepObjectStringNumber = ramda.filter(ramda.anyPass([isObject, isString, isNumber])); var keepKeyIfValueIsTruthy = ramda.mapObjIndexed(function (v, k) { return v && k; }); var destructObject = ramda.compose(filterFalsy, ramda.values, keepKeyIfValueIsTruthy); var transduceArgs = ramda.into([], ramda.compose(ramda.map(ramda.when(isObject, destructObject)), keepObjectStringNumber, filterFalsy)); /** * Conditionally joining classNames together. * * The cx function takes any number of arguments which can be a string, object * even nested arrays of strings and objects. * * The argument 'foo' is short for { foo: true }. * * If the value associated with a given key is falsy, that key won't be included in the output. * * @func * @category String * * @example * * R_.cx('Table', ['MagicTable'], {'Table--active': true }) // 'Table MagicTable Table--active' * R_.cx('Table', ['MagicTable'], {'Table--active': false }) // 'Table MagicTable' * R_.cx(['Table', ['MagicTable']]) // 'Table MagicTable' * * @sig String | [String] | Object -> String */ var cx = ramda.compose(joinWithSpace, ramda.flatten, transduceArgs, flattenArgs); /** * Returns true if property of object literal does not equals the given value. * * @func * @category Relation * * @example * * R_.propNotEq(1, 'a', { a: 1 }) // false * R_.propNotEq(1, 'a', { a: 2 }) // true * R_.propNotEq(1, 'a', {}) // true * * @sig a → String → Object → Boolean */ var propNotEq = ramda.complement(ramda.propEq); /** * Returns true if nested path of object literal does not contains given value. * * @func * @category Relation * * @example * * R_.pathNotEq(1, ['a', 'b'], { a: { b: 1 } }) // false * R_.pathNotEq(1, ['a', 'b'], { a: { b: 2 } }) // true * R_.pathNotEq(1, ['a', 'b'], {}) // true * R_.pathNotEq(1, ['a', 'b'], { a: {} }) // true * * @sig [String | Int] → a → {a} → Boolean */ var pathNotEq = ramda.complement(ramda.pathEq); /** * Creates list of length `n`. Every item in list equals to `input` parameter. * * @param {Number} n How many times replicate `input` * @param {a} input Value for replication * * @return List List of length `n`. Every item in list equals to `input` parameter * * @func * @category List * * @example * * R_.replicate(1, 6) // [6] * R_.replicate(2, 6) // [6, 6] * R_.replicate(3, 6) // [6, 6, 6] * * @sig Number -> a -> [a] */ var replicate = ramda.flip(ramda.repeat); /** * Creates pair. Every item of pair equals to input parameter. * * @param {a} input Value for duplication * * @return List Pair in which every item equals to `input` parameter * * @func * @category List * * @example * * R_.duplicate(1) // [1, 1] * * @sig a -> [a] */ var duplicate = replicate(2); /** * Copies keys of object to appropriate values. * * @func * @category Object * * * @param {Object} Object where should be keys copied as values. * * @return {Object} * * @example * * const actionTypes = R_.keyMirror({ * ITEM_REQUEST: null, * ITEM_SUCCESS: null, * ITEM_ERROR: null, * }); * * const action = { type: actionTypes.ITEM_REQUEST }; * * action.type === actionTypes.ITEM_REQUEST // true * * * @sig Object -> Object * */ var keyMirror = ramda.mapObjIndexed(ramda.nthArg(1)); /** * Creates object mirror from list of keys. * * @func * @category Object * * * @param {Array} keyList List of values representing the keys and values of resulting object. * * @return {Object} Object, where keys and appropriate values equals to value in `keyList`. * * @example * * const actionTypes = R_.valueMirror([ * 'ITEM_REQUEST', * 'ITEM_SUCCESS', * 'ITEM_ERROR', * ]); * * const action = { type: actionTypes.ITEM_REQUEST }; * * action.type === actionTypes.ITEM_REQUEST // true * actionTypes.ITEM_SUCCESS // "ITEM_SUCCESS" * * @sig [String] -> Object * */ var valueMirror = ramda.o(ramda.fromPairs, ramda.map(duplicate)); var wrapMapping = ramda.compose(ramda.juxt, ramda.flip(ramda.prepend)([ramda.last]), ramda.apply); /** * Map object keys. Mapping functions have both key and value as arguments. * * @func * @category Object * * @example * * R_.mapKeysWithValue((key, value) => value)({ foo: "bar" }) // { bar: "bar" } * * @sig ((String, a) -> b) -> Object -> Object */ var mapKeysWithValue = ramda.useWith(mapKeysAndValues, [wrapMapping, ramda.identity]); // prettier-ignore var camelizeObj = mapKeysAndValues(ramda.juxt([ramda.o(toCamelCase, ramda.head), ramda.o(function (x) { return camelizeKeys(x); }, ramda.last)])); var camelizeArray = ramda.map(function (x) { return camelizeKeys(x); }); /** * Recursively camelize all keys within an object or array * * @func * @category Object * * @param {any} x Object to transform * @return {any} * @example * * camelizeKeys({ * 'co-obj': { co_string: 'foo' }, * 'co-array': [0, null, { 'f-f': 'ff' }], * 'co-number': 1, * 'co-string': '1', * 'co-fn': head, * }); * * // { * // coArray: [ * // 0, * // null, * // { * // fF: 'ff' * // } * // ], * // coFn: [Function], * // coNumber: 1, * // coObj: { * // coString: 'foo' * // }, * // coString: '1' * // } * */ // prettier-ignore var camelizeKeys = ramda.cond([[isArray, camelizeArray], [isFunction, ramda.identity], [isNotNilObject, camelizeObj], [ramda.T, ramda.identity]]); /** * Returns `true` if `list` includes `item`. * * @func * @category List * * @param {Array} list * @param {any} item * @return {Boolean} Returns `true` if `list` includes `item`. * * @example * * R_.flipIncludes(['e', 'f'], 'e') // true * R_.flipIncludes(['e', 'f'], 'a') // false * * @sig [a] -> b -> Boolean */ var flipIncludes = ramda.flip(ramda.includes); /** * Returns `true` if if `list` includes `item`. * * Deprecated due to breaking change in Ramda. Use `R_.flipIncludes` instead. * * @func * @category List * * @param {Array} list * @param {any} item * @return {Boolean} Returns `true` if `list` includes `item`. * @deprecated * * @example * * R_.includes(['e', 'f'], 'e') // true * R_.includes(['a', 'f'], 'a') // false * * @sig [a] -> b -> Boolean */ var includes = flipIncludes; /** * Returns `false` if any of the items from `list` includes `item`. * * @func * @category List * * @param {Array} list * @param {any} item * @return {Boolean} Returns `false` if `list` includes `item`. * * @example * * R_.notFlipInclude(['e', 'f'], 'e') // false * R_.notFlipInclude(['e', 'f'], 'a') // true * * @sig [a] -> b -> Boolean */ var notFlipInclude = ramda.complement(flipIncludes); /** * Returns `false` if any of the items from `list` flipIncludes `item`. * * Deprecated due to breaking change in Ramda. Use `R_.notFlipInclude`. * * @func * @category List * * @param {Array} list * @param {any} item * @return {Boolean} Returns `false` if `list` flipIncludes `item`. * @deprecated * * @example * * R_.notInclude(['e', 'f'], 'e') // false * R_.notInclude(['a', 'f'], 'a') // true * * @sig [a] -> b -> Boolean */ var notInclude = notFlipInclude; /** * Creates curried pipe. The leftmost function determines the arity of curry. * * @func * @category Function * * @example * * const appendAndRejectNil = R_.pipeC(R.append, R.rejectNil); * const appendCAndRejectNil = appendAndRejectNil('c'); * appendCAndRejectNil(['a', null]) // ['a', 'c']; * */ var pipeC = ramda.converge(ramda.curry, [ramda.pipe]); /** * Creates curried compose. The rightmost function determines the arity of curry. * * @func * @category Function * * @example * * const appendAndRejectNil = R_.composeC(R.rejectNil, R.append); * const appendCAndRejectNil = appendAndRejectNil('c'); * appendCAndRejectNil(['a', null]) // ['a', 'c']; * */ var composeC = ramda.converge(ramda.curry, [ramda.compose]); /** * Takes a predicate, string `padString` and initial value. `padString` is contacted to the output string * everytime `pred` returns falsy value. * * @param {fn} pred Called after every contactation of `padString` * @param {string} padString String that is added everytime the `pred` returns falsy value * @param {string} init Intitial value * * @return String * @see padLeft, padRight, padRightUntil * * @func * @category String * * @example * * R_.padLeftUntil((x) => x.length === 10, '0')('1') // '0000000001' * * @sig (a -> Boolean) -> a -> a */ var padLeftUntil = ramda.useWith(ramda.until, [ramda.identity, ramda.concat, ramda.identity]); /** * Length of the output string, `padString` and initial value. * `padString` is repeatedly concated to `init` until the length of the string is equal to `lengthString`. * * @param {number} lengthString Length of the output string. * @param {string} padString * @param {string} init Intitial value * @see padRight, padLeftUntil, padRightUntil * * @return String * * @func * @category String * * @example * * R_.padLeft(10, '0')('1') // '00000000001' * R_.padLeft(-9, '0')('1') // '1' * R_.padLeft(1, '0')('1') // '1' * * @sig Number -> a -> a */ var padLeft = ramda.useWith(padLeftUntil, [lteThanLength, ramda.identity, ramda.identity]); /** * Takes a predicate, string `padString` and initial value. `padString` is append to the output string * everytime `pred` returns falsy value. * * @param {fn} pred Called after every append of `padString`. * @param {string} padString String that is added everytime the `pred` returns falsy value * @param {string} init Intitial value * * @return String * @see padLeft, padRight, padLeftUntil * * @func * @category String * * @example * * R_.padRightUntil((x) => x.length === 10, '0')('1') // '1000000000' * * @sig (a -> Boolean) -> a -> a */ var padRightUntil = ramda.useWith(ramda.until, [ramda.identity, ramda.flip(ramda.concat), ramda.identity]); /** * Length of the output string, `padString` and initial value. * `padString` is repeatedly appended to the `init` until the length of the string is equal to `lengthString`. * * @param {number} lengthString Length of the output string. * @param {string} padString * @param {string} init Intitial value * @see padLeft, padRightUntil, padRightUntil * * @return String * * @func * @category String * * @example * * R_.padRight(10, '0')('1') // '10000000000' *