UNPKG

declarative-js

Version:

_declarative-js_ is modern JavaScript library, that helps to: - tackle array transformation with built in JavaScript array api (e.g. `array.filter(toBe.unique())`), - provide a type-level solution for representing optional values instead of null referen

342 lines (341 loc) 14.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var fast_deep_equal_1 = __importDefault(require("fast-deep-equal")); var toObject_1 = require("../internal/toObject"); var toMap_1 = require("../internal/toMap"); var JMap_1 = require("../map/JMap"); var reducer_utils_1 = require("../internal/reducer.utils"); /** * Functions to be used in {@link Array.prototype.reduce} as a callback. * @see https://pavel-surinin.github.io/declarativejs/#/?id=reducers */ var Reducer; (function (Reducer) { function Map(data) { return new JMap_1.JMap(data); } Reducer.Map = Map; function ImmutableMap() { var map = new JMap_1.JMap(); return Object.defineProperty(map, reducer_utils_1.IMMUTABLE, { value: true, enumerable: false }); } Reducer.ImmutableMap = ImmutableMap; function ImmutableObject() { var object = {}; return Object.defineProperty(object, reducer_utils_1.IMMUTABLE, { value: true, enumerable: false }); } Reducer.ImmutableObject = ImmutableObject; function groupBy(getKey, transformer) { if (transformer === void 0) { transformer = function (x) { return x; }; } switch (typeof getKey) { case 'string': { var key_1 = getKey; return function (agr, value, index, array) { var derivedKey = value[key_1]; if (typeof derivedKey === 'string') { var derivedValue = agr.get(derivedKey); if (derivedValue) { derivedValue.push(transformer(value)); } else { agr.put(derivedKey, [transformer(value)]); } return reducer_utils_1.isLastElement(array, index) ? reducer_utils_1.finalizeMap(agr) : agr; } // tslint:disable-next-line:max-line-length throw new Error('Value of "' + key_1 + '" in groupBy ' + ' must be string, instead get: ' + typeof value[key_1]); }; } case 'function': { return function (agr, value, index, array) { var key = reducer_utils_1.valid(getKey(value)); var extractedValue = agr.get(key); if (extractedValue !== void 0) { extractedValue.push(transformer(value)); } else { agr.put(key, [transformer(value)]); } return reducer_utils_1.isLastElement(array, index) ? reducer_utils_1.finalizeMap(agr) : agr; }; } default: // tslint:disable-next-line:max-line-length throw new Error("Reducer.groupBy function accepts as a paramter string or callback, instead got " + typeof getKey); } } Reducer.groupBy = groupBy; /** * Function to be used in {@link Array.prototype.reduce} as a callback * to make from 2d array simple array * As second parameter in reduce function need to pass <code>[]</code> * @param {T[]} agr to collect in * @param {T[]} value to concatenate with * @returns {T[]} concatenated array * @see https://pavel-surinin.github.io/declarativejs/#/?id=flat */ Reducer.flat = function (agr, value) { if (Array.isArray(value)) { for (var index = 0; index < value.length; index++) { var element = value[index]; agr[agr.length] = element; } } else { agr[agr.length] = value; } return agr; }; function toMap(getKey, valueGetter) { var mapper = valueGetter === undefined ? toMap_1.toMapKeyMap(getKey) : toMap_1.toMapAndValue(getKey, valueGetter); return function _toMap(agr, value, index, array) { return mapper(agr, value, index, array); }; } Reducer.toMap = toMap; function toObject(getKey, valueGetter, merge) { var onDuplicate = merge || reducer_utils_1.onDuplacateDefaultFunction; var reducer = valueGetter === undefined ? toObject_1.toObjectValueObject(getKey) : toObject_1.toObjectAndValue(getKey, valueGetter, onDuplicate); return function _toObject(agr, value, index, array) { return reducer(agr, value, index, array); }; } Reducer.toObject = toObject; /** * Function to be used in {@link Array.prototype.reduce} as a callback. * Finds lowest value in array. Array must contain only numbers * @returns {number} lowest value in array. * @see https://pavel-surinin.github.io/declarativejs/#/?id=min */ // @ts-ignore function min(agr, value, index, array) { return reducer_utils_1.isLastElement(array, index) ? Math.min.apply(Math, array) : 0; } Reducer.min = min; /** * Function to be used in {@link Array.prototype.reduce} as a callback. * Finds highest value in array. Array must contain only numbers * @returns {number} highest value in array. * @see https://pavel-surinin.github.io/declarativejs/#/?id=max */ // @ts-ignore function max(agr, value, index, array) { return reducer_utils_1.isLastElement(array, index) ? Math.max.apply(Math, array) : 0; } Reducer.max = max; /** * Function to be used in {@link Array.prototype.reduce} as a callback. * Finds sum of values in array. Array must contain only numbers * @returns {number} sum of values in array. * @see https://pavel-surinin.github.io/declarativejs/#/?id=sum */ Reducer.sum = function (agr, value) { return agr + value; }; /** * Object merging strategy used in {@link Reducer#toMergedObject} * @see toMergedObject */ Reducer.MergeStrategy = { /** * Overrides value by duplicated key while merging objects */ OVERRIDE: function () { return true; }, /** * Keys in objects must be unique */ UNIQUE: function (aggregatorValue) { return aggregatorValue == null; }, /** * Keys in objects may have duplicates, but values in these key must be equal */ CHECKED: function (aggregatorValue, currentValue) { return aggregatorValue == null || fast_deep_equal_1.default(aggregatorValue, currentValue); } }; /** * Function to be used in {@link Array.prototype.reduce} as a callback. * Reduces array of objects to one object, There is three merge strategies * @param merge {@link MergeStrategy} = default is OVERRIDE * @see MergeStrategy * @see https://pavel-surinin.github.io/declarativejs/#/?id=tomergedobject */ function toMergedObject(isMergable) { if (isMergable === void 0) { isMergable = Reducer.MergeStrategy.OVERRIDE; } return function _toMergedObject(agr, value) { for (var _i = 0, _a = Object.keys(value); _i < _a.length; _i++) { var k = _a[_i]; var valueFromAggr = agr[k]; var valueFromObject = value[k]; if (!isMergable(valueFromAggr, valueFromObject, k)) { // tslint:disable-next-line:max-line-length throw new Error("Failed to merge objects. Check the merging predicate (\"strategy\") and objects in an array with key: " + k); } agr[k] = valueFromObject; } return agr; }; } Reducer.toMergedObject = toMergedObject; function zip(array, withFx) { var t = withFx ? withFx : function (t1, t2) { return [t1, t2]; }; var isZipped = false; var secondArrLength = array.length; return function _zip(agr, value, index) { if (isZipped) { return agr; } var arrayValue = array[index]; if (secondArrLength == index) { isZipped = true; return agr; } agr.push(t(value, arrayValue)); return agr; }; } Reducer.zip = zip; /** * Function to be used in {@link Array.prototype.reduce} as a callback. * Collects all arrays to arrays of arrays, with elements * at being grouped with elements from other arrays by same index. * The length of zipped array will be length of shortest array. * Almost the same as {@link Reducer.zip}, except zipAll accepts * multiple array to zip with. * * @export * @param {...Array[]} arraysToZip * @returns function to use in Array.reduce * @see Reducer.zip * @see https://pavel-surinin.github.io/declarativejs/#/?id=zipall */ function zipAll() { var arraysToZip = []; for (var _i = 0; _i < arguments.length; _i++) { arraysToZip[_i] = arguments[_i]; } var isZipped = false; var lengthOfArrays = arraysToZip.length; return function _zipAll(agr, currentValue, currentValueIndex) { if (isZipped) { return agr; } if (lengthOfArrays == currentValueIndex) { isZipped = true; return agr; } var zipee = [currentValue]; for (var index = 0; index < arraysToZip.length; index++) { zipee.push(arraysToZip[index][currentValueIndex]); } agr.push(zipee); return agr; }; } Reducer.zipAll = zipAll; /** * Function to be used in {@link Array.prototype.reduce} as a callback. * It does the opposite as {@link Reducer.zip} or {@link Reducer.zipAll}. * It collects from all zipped arrays one arrays, that was before zip. * Takes from each nested arrays and element and for each index will * collect to new array. * The length of and array will be the shortest length of arrays to unzip * * @export * @returns function to use in Array.reduce * @see Reducer.zip * @see Reducer.zipAll * @see https://pavel-surinin.github.io/declarativejs/#/?id=unzip */ function unzip() { var zippersLength; // @ts-ignore return function _unzip(agr, value, index, arrays) { if (zippersLength == null) { zippersLength = arrays.map(function (arr) { return arr.length; }).reduce(min); } for (var valueArrayIndex = 0; valueArrayIndex < zippersLength; valueArrayIndex++) { var agrUnzipArray = agr[valueArrayIndex]; if (agrUnzipArray) { agrUnzipArray.push(value[valueArrayIndex]); } else { agr[valueArrayIndex] = [value[valueArrayIndex]]; } } return agr; }; } Reducer.unzip = unzip; Reducer.Partition = function () { return [[], []]; }; function partitionBy(matches) { // tslint:disable-next-line var errorMessage = "Predicate for 'partitionBy' can be key of object, predicate function or partial object to match, instead got '" + matches + "'"; var predicate; if (typeof matches === 'string') { predicate = function (value) { return Boolean(value[matches]); }; } else if (typeof matches === 'function') { predicate = function (value) { return matches(value); }; } else if (typeof matches === 'object') { if (matches === null) { throw new Error(errorMessage); } predicate = function (value) { return Object.keys(matches).every(function (key) { return value[key] === matches[key]; }); }; } else { throw new Error(errorMessage); } return function _partitionByProp(agr, value) { if (predicate(value)) { agr[0].push(value); } else { agr[1].push(value); } return agr; }; } Reducer.partitionBy = partitionBy; /** * Function to be used in {@link Array.prototype.reduce} as a callback. * Groups pairs of consecutive elements together and returns them as an array of two values. * @see https://pavel-surinin.github.io/declarativejs/#/?id=pairwise */ function pairwise() { // @ts-ignore return function _pairwise(agr, value, index, array) { if (array.length - 1 != index) { agr.push([array[index], array[index + 1]]); } return agr; }; } Reducer.pairwise = pairwise; /** * Function to be used in {@link Array.prototype.reduce} as a callback. * Applies an accumulator function over the current element * and returns each intermediate result for accumulation * @param {function} accFunction accumulator function * @param {T} initial value * @see https://pavel-surinin.github.io/declarativejs/#/?id=scan */ function scan(accFunction, initial) { var acc = initial; return function _scan(agr, value) { var scanned = accFunction(acc, value); acc = accFunction(acc, value); agr.push(scanned); return agr; }; } Reducer.scan = scan; })(Reducer = exports.Reducer || (exports.Reducer = {}));