Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

unchanged

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

unchanged - npm Package Compare versions

Comparing version 1.5.2 to 2.0.0

dist/unchanged.cjs.js

19

CHANGELOG.md

@@ -5,2 +5,21 @@ # unchanged CHANGELOG

## 2.0.0
Rewrite in TypeScript!
**BREAKING CHANGES**
- `transform` has changed to be `setWith`, and the signature has changed as well (see [the documentation](README.md#setWith) for details)
**NEW FEATURES**
- Added [`is`](README.md#is) method for assertion
- Added function-first `*With` methods corresponding to each existing method (see [the documentation](README.md#transform-methods) for details)
- TypeScript typings
**ADDITIONAL CHANGES**
- Faster `get`s, `set`s, `merge`s, and `remove`s
- Distinct `main`, `module`, and `browser` builds for better universality of consumption
## 1.5.2

@@ -7,0 +26,0 @@

995

dist/unchanged.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('pathington'), require('curriable')) :
typeof define === 'function' && define.amd ? define(['exports', 'pathington', 'curriable'], factory) :
(factory((global.unchanged = {}),global.pathington,global.curriable));
}(this, (function (exports,pathington,curriable) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('curriable'), require('pathington')) :
typeof define === 'function' && define.amd ? define(['exports', 'curriable', 'pathington'], factory) :
(global = global || self, factory(global.unchanged = {}, global.curriable, global.pathington));
}(this, function (exports, curriable, pathington) { 'use strict';
// external dependencies
var O = Object;
var create = O.create,
getOwnPropertySymbols = O.getOwnPropertySymbols,
getPrototypeOf = O.getPrototypeOf,
keys = O.keys,
propertyIsEnumerable = O.propertyIsEnumerable;
var create = O.create, getOwnPropertySymbols = O.getOwnPropertySymbols, keys = O.keys, propertyIsEnumerable = O.propertyIsEnumerable;
var toStringObject = O.prototype.toString;
var toStringFunction = Function.prototype.toString;
var isArray = Array.isArray;
/**
* @constant {Symbol} REACT_ELEMENT
* @constant FUNCTION_NAME the RegExp expression matching function names
*/
// eslint-disable-next-line no-magic-numbers
var REACT_ELEMENT = typeof Symbol === 'function' && typeof Symbol.for === 'function' ? Symbol.for('react.element') : 0xeac7;
var FUNCTION_NAME = /^\s*function\s*([^\(]*)/i;
/**
* @constant {RegExp} FUNCTION_NAME
* @constant REACT_ELEMENT the symbol / number specific to react elements
*/
var FUNCTION_NAME = /^\s*function\s*([^\(]*)/i;
var REACT_ELEMENT = typeof Symbol === 'function' && typeof Symbol.for === 'function'
? Symbol.for('react.element')
: 0xeac7;
/**
* @function isArray
* @function cloneArray
*
* @description
* clone an array to a new array
*
* @param array the array to clone
* @returns the cloned array
*/
var isArray = Array.isArray;
var cloneArray = function cloneArray(array) {
var cloned = new array.constructor();
for (var index = 0; index < array.length; index++) {
cloned[index] = array[index];
}
return cloned;
var cloneArray = function (array) {
// @ts-ignore
var cloned = new array.constructor();
for (var index = 0; index < array.length; index++) {
cloned[index] = array[index];
}
return cloned;
};

@@ -45,18 +44,15 @@ /**

* @description
* a slimmer, simpler reduce than native (for performance)
* a targeted reduce method faster than the native
*
* @param {Array<any>} array the array to reduce
* @param {function} fn the function to reduce each iteration of the array with
* @param {any} initialValue the initial value of the reduction
* @returns {any} the reduced array value
* @param array the array to reduce
* @param fn the method to reduce each array value with
* @param initialValue the initial value of the reduction
* @returns the reduced value
*/
var reduce = function reduce(array, fn, initialValue) {
var value = initialValue;
for (var index = 0; index < array.length; index++) {
value = fn(value, array[index]);
}
return value;
var reduce = function (array, fn, initialValue) {
var value = initialValue;
for (var index = 0; index < array.length; index++) {
value = fn(value, array[index]);
}
return value;
};

@@ -67,22 +63,18 @@ /**

* @description
* get the own properties of an object, either keys or symbols
* get the all properties (keys and symbols) of the object passed
*
* @param {Object} object the object to get all keys and symbols of
* @returns {Array<string|symbol>} the own properties of the object
* @param object the object to get the properties of
* @returns the keys and symbols the object has
*/
var getOwnProperties = function getOwnProperties(object) {
var ownSymbols = getOwnPropertySymbols(object);
if (!ownSymbols.length) {
return keys(object);
}
return keys(object).concat(reduce(ownSymbols, function (enumerableSymbols, symbol) {
if (propertyIsEnumerable.call(object, symbol)) {
enumerableSymbols.push(symbol);
var getOwnProperties = function (object) {
var ownSymbols = getOwnPropertySymbols(object);
if (!ownSymbols.length) {
return keys(object);
}
return enumerableSymbols;
}, []));
return keys(object).concat(reduce(ownSymbols, function (enumerableSymbols, symbol) {
if (propertyIsEnumerable.call(object, symbol)) {
enumerableSymbols.push(symbol);
}
return enumerableSymbols;
}, []));
};

@@ -93,18 +85,16 @@ /**

* @description
* a simple implementation of Object.assign
* a targeted fallback if native Object.assign is unavailable
*
* @param {Object} target the target object
* @param {Object} source the object to merge into target
* @returns {Object} the shallowly-merged object
* @param target the object to shallowly merge into
* @param source the object to shallowly merge into target
* @returns the shallowly merged object
*/
var assignFallback = function assignFallback(target, source) {
if (!source) {
return target;
}
return reduce(getOwnProperties(source), function (clonedObject, property) {
clonedObject[property] = source[property];
return clonedObject;
}, Object(target));
var assignFallback = function (target, source) {
if (!source) {
return target;
}
return reduce(getOwnProperties(source), function (clonedObject, property) {
clonedObject[property] = source[property];
return clonedObject;
}, Object(target));
};

@@ -116,69 +106,55 @@ var assign = typeof O.assign === 'function' ? O.assign : assignFallback;

* @description
* can the object be cloned
*
* - the object exists and is an object
* - the object is not a Date or RegExp
* - the object is not a React element
* is the object passed considered cloneable
*
* @param {*} object the object to test
* @returns {boolean} can the object be merged
* @param object the object that is being checked for cloneability
* @returns whether the object can be cloned
*/
var isCloneable = function isCloneable(object) {
if (!object || typeof object !== 'object') {
return false;
}
var type = toStringObject.call(object);
return type !== '[object Date]' && type !== '[object RegExp]' && object.$$typeof !== REACT_ELEMENT;
var isCloneable = function (object) {
if (!object ||
typeof object !== 'object' ||
object.$$typeof === REACT_ELEMENT) {
return false;
}
var type = toStringObject.call(object);
return type !== '[object Date]' && type !== '[object RegExp]';
};
/**
* @function isGlobalConstructor
* @function isEmptyPath
*
* @description
* is the function passed a global constructor function
* is the path passed an empty path
*
* @param {function} fn the function to test
* @returns {boolean} is the function a global constructor
* @param path the path to check for emptiness
* @returns whether the path passed is considered empty
*/
var isGlobalConstructor = function isGlobalConstructor(fn) {
return typeof fn === 'function' && global[fn.name || toStringFunction.call(fn).split(FUNCTION_NAME)[1]] === fn;
var isEmptyPath = function (path) {
return path == null || (isArray(path) && !path.length);
};
/**
* @function callIfFunction
* @function isGlobalConstructor
*
* @description
* call the object passed if it is a function and return its return, else return undefined
* is the fn passed a global constructor
*
* @param {*} object the object to conditionally call if a function
* @param {*} context the context to apply to the call
* @param {Array<*>} parameters the parametesr to apply the function with
* @returns {*} the restulf of the call or undefined
* @param fn the fn to check if a global constructor
* @returns whether the fn passed is a global constructor
*/
var callIfFunction = function callIfFunction(object, context, parameters) {
return typeof object === 'function' ? object.apply(context, parameters) : void 0;
var isGlobalConstructor = function (fn) {
return typeof fn === 'function' &&
// @ts-ignore
global[fn.name || toStringFunction.call(fn).split(FUNCTION_NAME)[1]] === fn;
};
/**
* @function getShallowClone
* @function callIfFunction
*
* @description
* get a shallow clone of the value passed based on the type requested (maintaining prototype if possible)
* if the object passed is a function, call it and return its return, else return undefined
*
* @param {Array<*>|Object} object the object to clone
* @param {number|string} key the key to base the object type fromisReactElement(object) ||
* @returns {Array<*>|Object} a shallow clone of the value
* @param object the object to call if a function
* @param context the context to call the function with
* @param parameters the parameters to call the function with
* @returns the result of the function call, or undefined
*/
var getShallowClone = function getShallowClone(object) {
if (object.constructor === O) {
return assign({}, object);
}
if (isArray(object)) {
return cloneArray(object);
}
return isGlobalConstructor(object.constructor) ? {} : assign(create(getPrototypeOf(object)), object);
var callIfFunction = function (object, context, parameters) {
return typeof object === 'function' ? object.apply(context, parameters) : void 0;
};

@@ -189,10 +165,9 @@ /**

* @description
* get a new empty child for the type of key provided
* get a new empty child object based on the key passed
*
* @param {number|string} key the key to test
* @returns {Array|Object} the empty child
* @param key the key to base the empty child on
* @returns the empty object the child is built from
*/
var getNewEmptyChild = function getNewEmptyChild(key) {
return typeof key === 'number' ? [] : {};
var getNewEmptyChild = function (key) {
return typeof key === 'number' ? [] : {};
};

@@ -203,116 +178,78 @@ /**

* @description
* get a new empty object for the type of key provided
* get a new empty object based on the object passed
*
* @param {Array|Object} object the object to get an empty value of
* @returns {Array|Object} the empty object
* @param object the object to base the empty object on
* @returns an empty version of the object passed
*/
var getNewEmptyObject = function getNewEmptyObject(object) {
return isArray(object) ? [] : {};
};
var getNewEmptyObject = function (object) { return (isArray(object) ? [] : {}); };
/**
* @function cloneIfPossible
* @function getShallowClone
*
* @description
* clone the object passed if it is mergeable, else return itself
* create a shallow clone of the object passed, respecting its prototype
*
* @param {*} object he object to clone
* @returns {*} the cloned object
* @param object the object to clone
* @returns a shallow clone of the object passed
*/
var cloneIfPossible = function cloneIfPossible(object) {
return isCloneable(object) ? getShallowClone(object) : object;
var getShallowClone = function (object) {
if (object.constructor === O) {
return assign({}, object);
}
if (isArray(object)) {
return cloneArray(object);
}
return isGlobalConstructor(object.constructor)
? {}
: assign(create(object.__proto__), object);
};
/**
* @function getNewChildClone
* @function isSameValueZero
*
* @description
* get the shallow clone of the child when it is the correct type
* are the values equal based on SameValueZero
*
* @param {Array<*>|Object} object the object to clone
* @param {number|string} nextKey the key that the next object will be based from
* @returns {Array<*>|Object} the clone of the key at object
* @param value1 the first value to test
* @param value2 the second value to test
* @returns are the two values passed equal based on SameValueZero
*/
var getNewChildClone = function getNewChildClone(object, nextKey) {
return isCloneable(object) ? getShallowClone(object) : getNewEmptyChild(nextKey);
var isSameValueZero = function (value1, value2) {
return value1 === value2 || (value1 !== value1 && value2 !== value2);
};
/**
* @function getCoalescedValue
* @function cloneIfPossible
*
* @description
* get the value if it is not undefined, else get the fallback
*`
* @param {any} value the main value to return
* @param {any} fallbackValue the value to return if main is undefined
* @returns {any} the coalesced value
* clone the object if it can be cloned, otherwise return the object itself
*
* @param object the object to clone
* @returns a cloned version of the object, or the object itself if not cloneable
*/
var getCoalescedValue = function getCoalescedValue(value, fallbackValue) {
return value === void 0 ? fallbackValue : value;
var cloneIfPossible = function (object) {
return isCloneable(object) ? getShallowClone(object) : object;
};
/**
* @function onMatchAtPath
* @function getCloneOrEmptyObject
*
* @description
* when there is a match for the path requested, call onMatch, else return the noMatchValue
* if the object is cloneable, get a clone of the object, else get a new
* empty child object based on the key
*
* @param {Array<number|string>} path the path to find a match at
* @param {Array<*>|Object} object the object to find the path in
* @param {function} onMatch when a match is found, call this method
* @param {boolean} shouldClone should the object be cloned
* @param {*} noMatchValue when no match is found, return this value
* @param {number} [index=0] the index of the key to process
* @returns {*} either the return from onMatch or the noMatchValue
* @param object the object to clone
* @param nextKey the key to base the empty child object on
* @returns a clone of the object, or an empty child object
*/
var onMatchAtPath = function onMatchAtPath(path, object, onMatch, shouldClone, noMatchValue, index) {
if (index === void 0) {
index = 0;
}
var key = path[index];
var nextIndex = index + 1;
if (nextIndex === path.length) {
var result = object || shouldClone ? onMatch(object, key) : noMatchValue;
return shouldClone ? object : result;
}
if (shouldClone) {
object[key] = onMatchAtPath(path, getNewChildClone(object[key], path[nextIndex]), onMatch, shouldClone, noMatchValue, nextIndex);
return object;
}
return object && object[key] ? onMatchAtPath(path, object[key], onMatch, shouldClone, noMatchValue, nextIndex) : noMatchValue;
var getCloneOrEmptyObject = function (object, nextKey) {
return isCloneable(object) ? getShallowClone(object) : getNewEmptyChild(nextKey);
};
/**
* @function getMergedObject
* @function getCoalescedValue
*
* @description
* get the objects merged into a new object
* return the value if not undefined, otherwise return the fallback value
*
* @param {Array<*>|Object} object1 the object to merge into
* @param {Array<*>|Object} object2 the object to merge
* @param {boolean} isDeep is the object deeply merged
* @returns {Array<*>|Object} the merged object
* @param value the value to coalesce if undefined
* @param fallbackValue the value to coalesce to
* @returns the coalesced value
*/
var getMergedObject = function getMergedObject(object1, object2, isDeep) {
var isObject1Array = isArray(object1);
if (isObject1Array !== isArray(object2) || !isCloneable(object1)) {
return cloneIfPossible(object2);
}
if (isObject1Array) {
return object1.concat(object2);
}
var target = object1.constructor === O || isGlobalConstructor(object1.constructor) ? {} : create(getPrototypeOf(object1));
return reduce(getOwnProperties(object2), function (clone, key) {
clone[key] = isDeep && isCloneable(object2[key]) ? getMergedObject(object1[key], object2[key], isDeep) : object2[key];
return clone;
}, assign(target, object1));
};
var getCoalescedValue = function (value, fallbackValue) { return (value === void 0 ? fallbackValue : value); };
/**

@@ -322,112 +259,135 @@ * @function getParsedPath

* @description
* get the path array, either as-is if already an array, or parsed by pathington
* parse the path passed into an array path
*
* @param {Array<number|string>|number|string} path the path to parse
* @returns {Array<number|string>} the parsed path
* @param path the path to parse
* @returns the parsed path
*/
var getParsedPath = function getParsedPath(path) {
return isArray(path) ? path : pathington.parse(path);
};
var getParsedPath = function (path) { return (isArray(path) ? path : pathington.parse(path)); };
/**
* @function callNestedProperty
* @function getCloneAtPath
*
* @description
* parse the path passed and call the nested method at that path
* get a new object, cloned at the path specified while leveraging
* structural sharing for the rest of the properties
*
* @param {Array<number|string>|number|string} path the path to retrieve values from the object
* @param {*} context the context that the method is called with
* @param {Array<*>} parameters the parameters to call the method with
* @param {*} object the object to get values from
* @returns {*} the retrieved values
* @param path the path to clone at
* @param object the object with cloned children at path
* @param onMatch the method to call once the end of the path is reached
* @param index the path index
* @returns the object deeply cloned at the path specified
*/
var callNestedProperty = function callNestedProperty(path, context, parameters, object) {
var parsedPath = getParsedPath(path);
if (parsedPath.length === 1) {
return object ? callIfFunction(object[parsedPath[0]], context, parameters) : void 0;
}
return onMatchAtPath(parsedPath, object, function (ref, key) {
return callIfFunction(ref[key], context, parameters);
});
var getCloneAtPath = function (path, object, onMatch, index) {
var key = path[index];
var nextIndex = index + 1;
if (nextIndex === path.length) {
onMatch(object, key);
}
else {
object[key] = getCloneAtPath(path, getCloneOrEmptyObject(object[key], path[nextIndex]), onMatch, nextIndex);
}
return object;
};
/**
* @function getNestedProperty
* @function getDeepClone
*
* @description
* parse the path passed and get the nested property at that path
* get a clone of the object at the path specified
*
* @param {Array<number|string>|number|string} path the path to retrieve values from the object
* @param {*} object the object to get values from
* @param {*} noMatchValue an optional fallback value to be returned when the nested property isn't found
* @returns {*} the retrieved values
* @param path the path to clone at
* @param object the object to clone at the path
* @param onMatch once a patch match is found, the callback to fire
* @returns the clone of the object at path specified
*/
var getNestedProperty = function getNestedProperty(path, object, noMatchValue) {
var parsedPath = getParsedPath(path);
if (parsedPath.length === 1) {
return object ? getCoalescedValue(object[parsedPath[0]], noMatchValue) : noMatchValue;
}
return onMatchAtPath(parsedPath, object, function (ref, key) {
return getCoalescedValue(ref[key], noMatchValue);
}, false, noMatchValue);
var getDeepClone = function (path, object, onMatch) {
var parsedPath = getParsedPath(path);
var topLevelClone = getCloneOrEmptyObject(object, parsedPath[0]);
if (parsedPath.length === 1) {
onMatch(topLevelClone, parsedPath[0]);
return topLevelClone;
}
return getCloneAtPath(parsedPath, topLevelClone, onMatch, 0);
};
/**
* @function getDeepClone
* @function getMergedObject
*
* @description
* parse the path passed and clone the object at that path
* merge the source into the target, either deeply or shallowly
*
* @param {Array<number|string>|number|string} path the path to deeply modify the object on
* @param {Array<*>|Object} object the objeisCurrentKeyArrayct to modify
* @param {function} onMatch the callback to execute
* @returns {Array<*>|Object} the clone object
* @param target the object to merge into
* @param source the object being merged into the target
* @param isDeep is the merge a deep merge
* @returns the merged object
*/
var getDeepClone = function getDeepClone(path, object, onMatch) {
var parsedPath = getParsedPath(path);
var topLevelClone = isCloneable(object) ? getShallowClone(object) : getNewEmptyChild(parsedPath[0]);
if (parsedPath.length === 1) {
onMatch(topLevelClone, parsedPath[0]);
return topLevelClone;
}
return onMatchAtPath(parsedPath, topLevelClone, onMatch, true);
var getMergedObject = function (target, source, isDeep) {
var isObject1Array = isArray(target);
if (isObject1Array !== isArray(source) || !isCloneable(target)) {
return cloneIfPossible(source);
}
if (isObject1Array) {
return target.concat(source);
}
var targetClone = target.constructor === O || isGlobalConstructor(target.constructor)
? {}
: create(target.__proto__);
return reduce(getOwnProperties(source), function (clone, key) {
clone[key] =
isDeep && isCloneable(source[key])
? getMergedObject(target[key], source[key], isDeep)
: source[key];
return clone;
}, assign(targetClone, target));
};
/**
* @function hasNestedProperty
* @function getValueAtPath
*
* @description
* parse the path passed and determine if a value at the path exists
* get the value at the nested property, or the fallback provided
*
* @param {Array<number|string>|number|string} path the path to retrieve values from the object
* @param {*} object the object to get values from
* @returns {boolean} does the nested path exist
* @param path the path to get the value from
* @param object the object to get the value from at path
* @param noMatchValue the value returned if no match is found
* @returns the matching value, or the fallback provided
*/
var hasNestedProperty = function hasNestedProperty(path, object) {
return getNestedProperty(path, object) !== void 0;
var getValueAtPath = function (path, object, noMatchValue) {
var parsedPath = getParsedPath(path);
if (parsedPath.length === 1) {
return object
? getCoalescedValue(object[parsedPath[0]], noMatchValue)
: noMatchValue;
}
var ref = object;
var key = parsedPath[0];
for (var index = 0; index < parsedPath.length - 1; index++) {
if (!ref || !ref[key]) {
return noMatchValue;
}
ref = ref[key];
key = parsedPath[index + 1];
}
return ref ? getCoalescedValue(ref[key], noMatchValue) : noMatchValue;
};
/* eslint-disable eqeqeq */
/**
* @function isEmptyPath
* @function getFullPath
*
* @description
* is the object passed an empty key value
* get the path to add to, based on the object and fn passed
*
* @param {*} object the object to test
* @returns {boolean} is the object an empty key value
* @param path the path to add to
* @param object the object traversed by the path
* @param fn the function to transform the retrieved value with
* @returns the full path to add to
*/
var isEmptyPath = function isEmptyPath(object) {
return object == null || isArray(object) && !object.length;
var getFullPath = function (path, object, fn) {
var isPathEmpty = isEmptyPath(path);
var valueAtPath = isPathEmpty
? object
: fn
? fn(getValueAtPath(path, object))
: getValueAtPath(path, object);
return isArray(valueAtPath)
? isArray(path)
? path.concat([valueAtPath.length])
: (isPathEmpty ? '' : path) + "[" + valueAtPath.length + "]"
: path;
};
/* eslint-enable */
/**

@@ -437,232 +397,373 @@ * @function splice

* @description
* splice a single item from the array
* a faster, more targeted version of the native splice
*
* @param {Array<*>} array array to splice from
* @param {number} splicedIndex index to splice at
* @param array the array to remove the value from
* @param splicedIndex the index of the value to remove
*/
var splice = function splice(array, splicedIndex) {
if (array.length) {
var length = array.length;
var index = splicedIndex;
while (index < length - 1) {
array[index] = array[index + 1];
++index;
var splice = function (array, splicedIndex) {
if (array.length) {
var length_1 = array.length;
var index = splicedIndex;
while (index < length_1 - 1) {
array[index] = array[index + 1];
++index;
}
--array.length;
}
--array.length;
}
};
// external dependencies
/**
* @function assign
* @function throwInvalidFnError
*
* @description
* get the shallowly-merged object at path
* throw the TypeError based on the invalid handler
*
* @param {Array<number|string>|null|number|string} path the path to match on the object
* @param {Array<*>|Object} objectToAssign the object to merge
* @param {Array<*>|Object} object the object to merge with
* @returns {Array<*>|Object} the new merged object
* @throws
*/
var throwInvalidFnError = function () {
throw new TypeError('handler passed is not of type "function".');
};
var assign$1 = curriable.curry(function (path, objectToAssign, object) {
if (!isCloneable(object)) {
return objectToAssign;
}
return isEmptyPath(path) ? getMergedObject(object, objectToAssign, false) : getDeepClone(path, object, function (ref, key) {
ref[key] = getMergedObject(ref[key], objectToAssign, false);
});
});
// utils
var isArray$1 = Array.isArray;
var slice = Array.prototype.slice;
/**
* @function call
* @function createCall
*
* @description
* call a nested method at the path requested with the parameters provided
* create handlers for call / callWith
*
* @param {Array<number|string>|null|number|string} path the path to get the value at
* @param {Array<*>} parameters the parameters to call the method with
* @param {Array<*>|Object} object the object to call the method from
* @param {*} context the context to set as "this" in the function call
* @param isWithHandler is the method using a with handler
* @returns call / callWith
*/
var call = curriable.curry(function (path, parameters, object, context) {
if (context === void 0) {
context = object;
}
return isEmptyPath(path) ? callIfFunction(object, context, parameters) : callNestedProperty(path, context, parameters, object);
}, // eslint-disable-next-line no-magic-numbers
3);
var createCall = function (isWithHandler) {
if (isWithHandler) {
return function (fn, path, parameters, object, context) {
if (context === void 0) { context = object; }
if (typeof fn !== 'function') {
throwInvalidFnError();
}
var extraArgs = slice.call(arguments, 5);
if (isEmptyPath(path)) {
return callIfFunction(fn.apply(void 0, [object].concat(extraArgs)), context, parameters);
}
var value = getValueAtPath(path, object);
if (value === void 0) {
return;
}
var result = fn.apply(void 0, [value].concat(extraArgs));
return callIfFunction(result, context, parameters);
};
}
return function (path, parameters, object, context) {
if (context === void 0) { context = object; }
var callable = isEmptyPath(path)
? object
: getValueAtPath(path, object);
return callIfFunction(callable, context, parameters);
};
};
/**
* @function get
* @function createGet
*
* @description
* get the value to the object at the path requested
* create handlers for get / getWith
*
* @param {Array<number|string>|null|number|string} path the path to get the value at
* @param {Array<*>|Object} object the object to get the value from
* @returns {*} the value requested
* @param isWithHandler is the method using a with handler
* @returns get / getWith
*/
var get = curriable.curry(function (path, object) {
return isEmptyPath(path) ? object : getNestedProperty(path, object);
});
var createGet = function (isWithHandler) {
if (isWithHandler) {
return function (fn, path, object) {
if (typeof fn !== 'function') {
throwInvalidFnError();
}
var extraArgs = slice.call(arguments, 4);
if (isEmptyPath(path)) {
return fn.apply(void 0, [object].concat(extraArgs));
}
var value = getValueAtPath(path, object);
return value === void 0 ? value : fn.apply(void 0, [value].concat(extraArgs));
};
}
return function (path, object) {
return isEmptyPath(path) ? object : getValueAtPath(path, object);
};
};
/**
* @function getOr
* @function createGetOr
*
* @description
* get the value to the object at the path requested, or noMatchValue if nothing
* is there.
* create handlers for getOr / getWithOr
*
* @param {*} noMatchValue the fallback value if nothing is found at the given path
* @param {Array<number|string>|null|number|string} path the path to get the value at
* @param {Array<*>|Object} object the object to get the value from
* @returns {*} the value requested
* @param isWithHandler is the method using a with handler
* @returns getOr / getWithOr
*/
var getOr = curriable.curry(function (noMatchValue, path, object) {
return isEmptyPath(path) ? object : getNestedProperty(path, object, noMatchValue);
});
var createGetOr = function (isWithHandler) {
if (isWithHandler) {
return function (fn, noMatchValue, path, object) {
if (typeof fn !== 'function') {
throwInvalidFnError();
}
var extraArgs = slice.call(arguments, 4);
if (isEmptyPath(path)) {
return fn.apply(void 0, [object].concat(extraArgs));
}
var value = getValueAtPath(path, object);
return value === void 0 ? noMatchValue : fn.apply(void 0, [value].concat(extraArgs));
};
}
return function (noMatchValue, path, object) {
return isEmptyPath(path) ? object : getValueAtPath(path, object, noMatchValue);
};
};
/**
* @function has
* @function createHas
*
* @description
* does the nested path exist on the object
* create handlers for has / hasWith
*
* @param {Array<number|string>|null|number|string} path the path to match on the object
* @param {Array<*>|Object} object the object to get the value from
* @returns {boolean} does the path exist
* @param isWithHandler is the method using a with handler
* @returns has / hasWith
*/
/* eslint-disable eqeqeq */
var has = curriable.curry(function (path, object) {
return isEmptyPath(path) ? object != null : hasNestedProperty(path, object);
});
/* eslint-enable */
var createHas = function (isWithHandler) {
if (isWithHandler) {
return function (fn, path, object) {
if (typeof fn !== 'function') {
throwInvalidFnError();
}
var extraArgs = slice.call(arguments, 3);
if (isEmptyPath(path)) {
return !!fn.apply(void 0, [object].concat(extraArgs));
}
var value = getValueAtPath(path, object);
return value !== void 0 && !!fn.apply(void 0, [value].concat(extraArgs));
};
}
return function (path, object) {
return isEmptyPath(path)
? object != null
: getValueAtPath(path, object) !== void 0;
};
};
/**
* @function merge
* @function createIs
*
* @description
* get the deeply-merged object at path
* create handlers for is / isWith
*
* @param {Array<number|string>|null|number|string} path the path to match on the object
* @param {Array<*>|Object} objectToMerge the object to merge
* @param {Array<*>|Object} object the object to merge with
* @returns {Array<*>|Object} the new merged object
* @param isWithHandler is the method using a with handler
* @returns is / isWith
*/
var merge = curriable.curry(function (path, objectToMerge, object) {
if (!isCloneable(object)) {
return objectToMerge;
}
return isEmptyPath(path) ? getMergedObject(object, objectToMerge, true) : getDeepClone(path, object, function (ref, key) {
ref[key] = getMergedObject(ref[key], objectToMerge, true);
});
});
var createIs = function (isWithHandler) {
if (isWithHandler) {
return function (fn, path, value, object) {
if (typeof fn !== 'function') {
throwInvalidFnError();
}
var extraArgs = slice.call(arguments, 4);
if (isEmptyPath(path)) {
return isSameValueZero(fn.apply(void 0, [object].concat(extraArgs)), value);
}
return isSameValueZero(fn.apply(void 0, [getValueAtPath(path, object)].concat(extraArgs)), value);
};
}
return function (path, value, object) {
return isEmptyPath(path)
? isSameValueZero(object, value)
: isSameValueZero(getValueAtPath(path, object), value);
};
};
/**
* @function removeobject with quoted keys
* @function createMerge
*
* @description
* remove the value in the object at the path requested
* create handlers for merge / mergeWith
*
* @param {Array<number|string>|number|string} path the path to remove the value at
* @param {Array<*>|Object} object the object to remove the value from
* @returns {Array<*>|Object} a new object with the same structure and the value removed
* @param isWithHandler is the method using a with handler
* @param isDeep is the handler for a deep merge or shallow
* @returns merge / mergeWith
*/
var remove = curriable.curry(function (path, object) {
if (isEmptyPath(path)) {
return getNewEmptyObject(object);
}
return hasNestedProperty(path, object) ? getDeepClone(path, object, function (ref, key) {
if (isArray(ref)) {
splice(ref, key);
} else {
delete ref[key];
var createMerge = function (isWithHandler, isDeep) {
if (isWithHandler) {
return function (fn, path, object) {
if (typeof fn !== 'function') {
throwInvalidFnError();
}
var extraArgs = slice.call(arguments, 3);
if (!isCloneable(object)) {
return fn.apply(void 0, [object].concat(extraArgs));
}
if (isEmptyPath(path)) {
var objectToMerge = fn.apply(void 0, [object].concat(extraArgs));
return objectToMerge
? getMergedObject(object, objectToMerge, isDeep)
: object;
}
var hasChanged = false;
var result = getDeepClone(path, object, function (ref, key) {
var objectToMerge = fn.apply(void 0, [ref[key]].concat(extraArgs));
if (objectToMerge) {
ref[key] = getMergedObject(ref[key], objectToMerge, isDeep);
hasChanged = true;
}
});
return hasChanged ? result : object;
};
}
}) : object;
});
return function (path, objectToMerge, object) {
if (!isCloneable(object)) {
return objectToMerge;
}
return isEmptyPath(path)
? getMergedObject(object, objectToMerge, true)
: getDeepClone(path, object, function (ref, key) {
ref[key] = getMergedObject(ref[key], objectToMerge, isDeep);
});
};
};
/**
* @function set
* @function createRemove
*
* @description
* set the value in the object at the path requested
* create handlers for remove / removeWith
*
* @param {Array<number|string>|number|string} path the path to set the value at
* @param {*} value the value to set
* @param {Array<*>|Object} object the object to set the value in
* @returns {Array<*>|Object} a new object with the same structure and the value assigned
* @param isWithHandler is the method using a with handler
* @returns remove / removeWith
*/
var set = curriable.curry(function (path, value, object) {
return isEmptyPath(path) ? value : getDeepClone(path, object, function (ref, key) {
ref[key] = value;
});
});
var createRemove = function (isWithHandler) {
if (isWithHandler) {
return function (fn, path, object) {
if (typeof fn !== 'function') {
throwInvalidFnError();
}
var extraArgs = slice.call(arguments, 3);
if (isEmptyPath(path)) {
var emptyObject = getNewEmptyObject(object);
return fn.apply(void 0, [emptyObject].concat(extraArgs)) ? emptyObject : object;
}
var value = getValueAtPath(path, object);
return value !== void 0 && fn.apply(void 0, [value].concat(extraArgs))
? getDeepClone(path, object, function (ref, key) {
if (isArray$1(ref)) {
splice(ref, key);
}
else {
delete ref[key];
}
})
: object;
};
}
return function (path, object) {
if (isEmptyPath(path)) {
return getNewEmptyObject(object);
}
return getValueAtPath(path, object) !== void 0
? getDeepClone(path, object, function (ref, key) {
if (isArray$1(ref)) {
splice(ref, key);
}
else {
delete ref[key];
}
})
: object;
};
};
/**
* @function transform
* @function createSet
*
* @description
* perform same operation as set, but using a callback function that receives
* the value (and additional parameters, if provided) to get the value to set
* create handlers for set / setWith
*
* @param {Array<number|string>|number|string} path the path to set the value at
* @param {function} fn the function to transform the retrieved value with
* @param {Array<*>|Object} object the object to set the value in
* @param {...Array<any>} extraArgs additional arguments to pass to the transform function
* @returns {Array<*>|Object} a new object with the same structure and the value assigned
* @param isWithHandler is the method using a with handler
* @returns set / setWith
*/
var transform = curriable.curry(function (path, fn, object) {
for (var _len = arguments.length, extraArgs = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
extraArgs[_key - 3] = arguments[_key];
}
return isEmptyPath(path) ? fn.apply(void 0, [object].concat(extraArgs)) : getDeepClone(path, object, function (ref, key) {
return ref[key] = fn.apply(void 0, [ref[key]].concat(extraArgs));
});
}, // eslint-disable-next-line no-magic-numbers
3);
var createSet = function (isWithHandler) {
if (isWithHandler) {
return function (fn, path, object) {
if (typeof fn !== 'function') {
throwInvalidFnError();
}
var extraArgs = slice.call(arguments, 3);
return isEmptyPath(path)
? fn.apply(void 0, [object].concat(extraArgs)) : getDeepClone(path, object, function (ref, key) {
ref[key] = fn.apply(void 0, [ref[key]].concat(extraArgs));
});
};
}
return function (path, value, object) {
return isEmptyPath(path)
? value
: getDeepClone(path, object, function (ref, key) {
ref[key] = value;
});
};
};
/**
* @function add
* @function createAdd
*
* @description
* add the value to the object at the path requested
* create handlers for add / addWith
*
* @param {Array<number|string>|null|number|string} path the path to assign the value at
* @param {*} value the value to assign
* @param {Array<*>|Object} object the object to assignobject the value in
* @returns {Array<*>|Object} a new object with the same structure and the value added
* @param isWithHandler is the method using a with handler
* @returns add / addWith
*/
var createAdd = function (isWithHandler) {
var add = createSet(isWithHandler);
if (isWithHandler) {
return function (fn, path, object) {
return add.apply(this, [fn, getFullPath(path, object, fn), object].concat(slice.call(arguments, 3)));
};
}
return function (path, value, object) { return add(getFullPath(path, object), value, object); };
};
var add = curriable.curry(function (path, value, object) {
var isPathEmpty = isEmptyPath(path);
var valueAtPath = isPathEmpty ? object : getNestedProperty(path, object);
var fullPath = isArray(valueAtPath) ? isArray(path) ? path.concat([valueAtPath.length]) : (isPathEmpty ? '' : path) + "[" + valueAtPath.length + "]" : path;
return set(fullPath, value, object);
});
// external dependencies
var add = curriable.curry(createAdd(false), 3);
var addWith = curriable.curry(createAdd(true), 3);
var assign$1 = curriable.curry(createMerge(false, false), 3);
var assignWith = curriable.curry(createMerge(true, false), 3);
var call = curriable.curry(createCall(false), 3);
var callWith = curriable.curry(createCall(true), 4);
var get = curriable.curry(createGet(false), 2);
var getOr = curriable.curry(createGetOr(false), 3);
var getWith = curriable.curry(createGet(true), 3);
var getWithOr = curriable.curry(createGetOr(true), 4);
var has = curriable.curry(createHas(false), 2);
var hasWith = curriable.curry(createHas(true), 3);
var is = curriable.curry(createIs(false), 3);
var isWith = curriable.curry(createIs(true), 4);
var merge = curriable.curry(createMerge(false, true), 3);
var mergeWith = curriable.curry(createMerge(true, true), 3);
var remove = curriable.curry(createRemove(false), 2);
var removeWith = curriable.curry(createRemove(true), 3);
var set = curriable.curry(createSet(false), 3);
var setWith = curriable.curry(createSet(true), 3);
exports.__ = curriable.__;
exports.add = add;
exports.addWith = addWith;
exports.assign = assign$1;
exports.assignWith = assignWith;
exports.call = call;
exports.callWith = callWith;
exports.get = get;
exports.getOr = getOr;
exports.getWith = getWith;
exports.getWithOr = getWithOr;
exports.has = has;
exports.hasWith = hasWith;
exports.is = is;
exports.isWith = isWith;
exports.merge = merge;
exports.mergeWith = mergeWith;
exports.remove = remove;
exports.removeWith = removeWith;
exports.set = set;
exports.transform = transform;
exports.add = add;
exports.setWith = setWith;
Object.defineProperty(exports, '__esModule', { value: true });
})));
}));
//# sourceMappingURL=unchanged.js.map

@@ -1,1 +0,1 @@

!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("pathington"),require("curriable")):"function"==typeof define&&define.amd?define(["exports","pathington","curriable"],t):t(n.unchanged={},n.pathington,n.curriable)}(this,function(n,t,r){"use strict";var i=Object,f=i.create,e=i.getOwnPropertySymbols,a=i.getPrototypeOf,o=i.keys,u=i.propertyIsEnumerable,c=i.prototype.toString,l=Function.prototype.toString,y="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("react.element"):60103,p=/^\s*function\s*([^\(]*)/i,g=Array.isArray,s=function(n,t,r){for(var e=r,o=0;o<n.length;o++)e=t(e,n[o]);return e},v=function(r){var n=e(r);return n.length?o(r).concat(s(n,function(n,t){return u.call(r,t)&&n.push(t),n},[])):o(r)},d="function"==typeof i.assign?i.assign:function(n,r){return r?s(v(r),function(n,t){return n[t]=r[t],n},Object(n)):n},h=function(n){if(!n||"object"!=typeof n)return!1;var t=c.call(n);return"[object Date]"!==t&&"[object RegExp]"!==t&&n.$$typeof!==y},b=function(n){return"function"==typeof n&&global[n.name||l.call(n).split(p)[1]]===n},m=function(n,t,r){return"function"==typeof n?n.apply(t,r):void 0},j=function(n){return n.constructor===i?d({},n):g(n)?function(n){for(var t=new n.constructor,r=0;r<n.length;r++)t[r]=n[r];return t}(n):b(n.constructor)?{}:d(f(a(n)),n)},O=function(n){return"number"==typeof n?[]:{}},S=function(n,t){return void 0===n?t:n},_=function n(t,r,e,o,u,c){void 0===c&&(c=0);var i,f,a=t[c],l=c+1;if(l!==t.length)return o?(r[a]=n(t,(i=r[a],f=t[l],h(i)?j(i):O(f)),e,o,u,l),r):r&&r[a]?n(t,r[a],e,o,u,l):u;var y=r||o?e(r,a):u;return o?r:y},x=function r(e,o,u){var n,t=g(e);if(t!==g(o)||!h(e))return h(n=o)?j(n):n;if(t)return e.concat(o);var c=e.constructor===i||b(e.constructor)?{}:f(a(e));return s(v(o),function(n,t){return n[t]=u&&h(o[t])?r(e[t],o[t],u):o[t],n},d(c,e))},w=function(n){return g(n)?n:t.parse(n)},A=function(n,t,r){var e=w(n);return 1===e.length?t?S(t[e[0]],r):r:_(e,t,function(n,t){return S(n[t],r)},!1,r)},P=function(n,t,r){var e=w(n),o=h(t)?j(t):O(e[0]);return 1===e.length?(r(o,e[0]),o):_(e,o,r,!0)},q=function(n,t){return void 0!==A(n,t)},E=function(n){return null==n||g(n)&&!n.length},$=r.curry(function(n,r,t){return h(t)?E(n)?x(t,r,!1):P(n,t,function(n,t){n[t]=x(n[t],r,!1)}):r}),k=r.curry(function(n,t,r,e){return void 0===e&&(e=r),E(n)?m(r,e,t):(o=e,u=t,c=r,1===(i=w(n)).length?c?m(c[i[0]],o,u):void 0:_(i,c,function(n,t){return m(n[t],o,u)}));var o,u,c,i},3),D=r.curry(function(n,t){return E(n)?t:A(n,t)}),F=r.curry(function(n,t,r){return E(t)?r:A(t,r,n)}),I=r.curry(function(n,t){return E(n)?null!=t:q(n,t)}),M=r.curry(function(n,r,t){return h(t)?E(n)?x(t,r,!0):P(n,t,function(n,t){n[t]=x(n[t],r,!0)}):r}),R=r.curry(function(n,t){return E(n)?g(t)?[]:{}:q(n,t)?P(n,t,function(n,t){g(n)?function(n,t){if(n.length){for(var r=n.length,e=t;e<r-1;)n[e]=n[e+1],++e;--n.length}}(n,t):delete n[t]}):t}),z=r.curry(function(n,r,t){return E(n)?r:P(n,t,function(n,t){n[t]=r})}),B=r.curry(function(n,r,t){for(var e=arguments.length,o=new Array(3<e?e-3:0),u=3;u<e;u++)o[u-3]=arguments[u];return E(n)?r.apply(void 0,[t].concat(o)):P(n,t,function(n,t){return n[t]=r.apply(void 0,[n[t]].concat(o))})},3),C=r.curry(function(n,t,r){var e=E(n),o=e?r:A(n,r),u=g(o)?g(n)?n.concat([o.length]):(e?"":n)+"["+o.length+"]":n;return z(u,t,r)});n.__=r.__,n.assign=$,n.call=k,n.get=D,n.getOr=F,n.has=I,n.merge=M,n.remove=R,n.set=z,n.transform=B,n.add=C,Object.defineProperty(n,"__esModule",{value:!0})});
(function(a,b){"object"==typeof exports&&"undefined"!=typeof module?b(exports,require("curriable"),require("pathington")):"function"==typeof define&&define.amd?define(["exports","curriable","pathington"],b):(a=a||self,b(a.unchanged={},a.curriable,a.pathington))})(this,function(a,b,c){"use strict";var d=Object,e=d.create,f=d.getOwnPropertySymbols,g=d.keys,h=d.propertyIsEnumerable,i=d.prototype.toString,j=Function.prototype.toString,k=Array.isArray,l=/^\s*function\s*([^\(]*)/i,m="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("react.element"):60103,n=function(a){for(var b=new a.constructor,c=0;c<a.length;c++)b[c]=a[c];return b},o=function(a,b,c){for(var d=c,e=0;e<a.length;e++)d=b(d,a[e]);return d},p=function(a){var b=f(a);return b.length?g(a).concat(o(b,function(b,c){return h.call(a,c)&&b.push(c),b},[])):g(a)},q="function"==typeof d.assign?d.assign:function(a,b){return b?o(p(b),function(a,c){return a[c]=b[c],a},Object(a)):a},r=function(a){if(!a||"object"!=typeof a||a.$$typeof===m)return!1;var b=i.call(a);return"[object Date]"!==b&&"[object RegExp]"!==b},s=function(a){return null==a||k(a)&&!a.length},t=function(a){return"function"==typeof a&&global[a.name||j.call(a).split(l)[1]]===a},u=function(a,b,c){return"function"==typeof a?a.apply(b,c):void 0},v=function(a){return"number"==typeof a?[]:{}},w=function(a){return k(a)?[]:{}},x=function(a){return a.constructor===d?q({},a):k(a)?n(a):t(a.constructor)?{}:q(e(a.__proto__),a)},y=function(a,b){return a===b||a!==a&&b!==b},z=function(a){return r(a)?x(a):a},A=function(a,b){return r(a)?x(a):v(b)},B=function(a,b){return void 0===a?b:a},C=function(a){return k(a)?a:c.parse(a)},D=function(a,b,c,d){var e=a[d],f=d+1;return f===a.length?c(b,e):b[e]=D(a,A(b[e],a[f]),c,f),b},E=function(a,b,c){var d=C(a),e=A(b,d[0]);return 1===d.length?(c(e,d[0]),e):D(d,e,c,0)},F=function(a,b,c){var f=k(a);if(f!==k(b)||!r(a))return z(b);if(f)return a.concat(b);var g=a.constructor===d||t(a.constructor)?{}:e(a.__proto__);return o(p(b),function(d,e){return d[e]=c&&r(b[e])?F(a[e],b[e],c):b[e],d},q(g,a))},G=function(a,b,c){var d=C(a);if(1===d.length)return b?B(b[d[0]],c):c;for(var e=b,f=d[0],g=0;g<d.length-1;g++){if(!e||!e[f])return c;e=e[f],f=d[g+1]}return e?B(e[f],c):c},H=function(a,b,c){var d=s(a),e=d?b:c?c(G(a,b)):G(a,b);return k(e)?k(a)?a.concat([e.length]):(d?"":a)+"["+e.length+"]":a},I=function(a,b){if(a.length){for(var c=a.length,d=b;d<c-1;)a[d]=a[d+1],++d;--a.length}},J=function(){throw new TypeError("handler passed is not of type \"function\".")},K=Array.isArray,L=Array.prototype.slice,M=function(a){return a?function(a,b,c,d,e){void 0===e&&(e=d),"function"!=typeof a&&J();var f=L.call(arguments,5);if(s(b))return u(a.apply(void 0,[d].concat(f)),e,c);var g=G(b,d);if(void 0!==g){var h=a.apply(void 0,[g].concat(f));return u(h,e,c)}}:function(a,b,c,d){void 0===d&&(d=c);var e=s(a)?c:G(a,c);return u(e,d,b)}},N=function(a){return a?function(a,b,c){"function"!=typeof a&&J();var d=L.call(arguments,4);if(s(b))return a.apply(void 0,[c].concat(d));var e=G(b,c);return void 0===e?e:a.apply(void 0,[e].concat(d))}:function(a,b){return s(a)?b:G(a,b)}},O=function(a){return a?function(a,b,c,d){"function"!=typeof a&&J();var e=L.call(arguments,4);if(s(c))return a.apply(void 0,[d].concat(e));var f=G(c,d);return void 0===f?b:a.apply(void 0,[f].concat(e))}:function(a,b,c){return s(b)?c:G(b,c,a)}},P=function(a){return a?function(a,b,c){"function"!=typeof a&&J();var d=L.call(arguments,3);if(s(b))return!!a.apply(void 0,[c].concat(d));var e=G(b,c);return void 0!==e&&!!a.apply(void 0,[e].concat(d))}:function(a,b){return s(a)?null!=b:void 0!==G(a,b)}},Q=function(a){return a?function(a,b,c,d){"function"!=typeof a&&J();var e=L.call(arguments,4);return s(b)?y(a.apply(void 0,[d].concat(e)),c):y(a.apply(void 0,[G(b,d)].concat(e)),c)}:function(a,b,c){return s(a)?y(c,b):y(G(a,c),b)}},R=function(a,b){return a?function(a,c,d){"function"!=typeof a&&J();var e=L.call(arguments,3);if(!r(d))return a.apply(void 0,[d].concat(e));if(s(c)){var f=a.apply(void 0,[d].concat(e));return f?F(d,f,b):d}var g=!1,h=E(c,d,function(c,d){var f=a.apply(void 0,[c[d]].concat(e));f&&(c[d]=F(c[d],f,b),g=!0)});return g?h:d}:function(a,c,d){return r(d)?s(a)?F(d,c,!0):E(a,d,function(a,d){a[d]=F(a[d],c,b)}):c}},S=function(a){return a?function(a,b,c){"function"!=typeof a&&J();var d=L.call(arguments,3);if(s(b)){var e=w(c);return a.apply(void 0,[e].concat(d))?e:c}var f=G(b,c);return void 0!==f&&a.apply(void 0,[f].concat(d))?E(b,c,function(a,b){K(a)?I(a,b):delete a[b]}):c}:function(a,b){return s(a)?w(b):void 0===G(a,b)?b:E(a,b,function(a,b){K(a)?I(a,b):delete a[b]})}},T=function(a){return a?function(a,b,c){"function"!=typeof a&&J();var d=L.call(arguments,3);return s(b)?a.apply(void 0,[c].concat(d)):E(b,c,function(b,c){b[c]=a.apply(void 0,[b[c]].concat(d))})}:function(a,b,c){return s(a)?b:E(a,c,function(a,c){a[c]=b})}},U=function(a){var b=T(a);return a?function(a,c,d){return b.apply(this,[a,H(c,d,a),d].concat(L.call(arguments,3)))}:function(a,c,d){return b(H(a,d),c,d)}},V=b.curry(U(!1),3),W=b.curry(U(!0),3),X=b.curry(R(!1,!1),3),Y=b.curry(R(!0,!1),3),Z=b.curry(M(!1),3),$=b.curry(M(!0),4),_=b.curry(N(!1),2),aa=b.curry(O(!1),3),ba=b.curry(N(!0),3),ca=b.curry(O(!0),4),da=b.curry(P(!1),2),ea=b.curry(P(!0),3),fa=b.curry(Q(!1),3),ga=b.curry(Q(!0),4),ha=b.curry(R(!1,!0),3),ia=b.curry(R(!0,!0),3),ja=b.curry(S(!1),2),ka=b.curry(S(!0),3),la=b.curry(T(!1),3),ma=b.curry(T(!0),3);a.__=b.__,a.add=V,a.addWith=W,a.assign=X,a.assignWith=Y,a.call=Z,a.callWith=$,a.get=_,a.getOr=aa,a.getWith=ba,a.getWithOr=ca,a.has=da,a.hasWith=ea,a.is=fa,a.isWith=ga,a.merge=ha,a.mergeWith=ia,a.remove=ja,a.removeWith=ka,a.set=la,a.setWith=ma,Object.defineProperty(a,"__esModule",{value:!0})});
{
"author": "tony_quetano@planttheidea.com",
"ava": {
"failFast": true,
"files": [
"test/*.js"
],
"require": [
"@babel/register"
],
"sources": [
"src/*.js"
],
"verbose": true
},
"browser": "dist/unchanged.js",
"browserslist": [

@@ -28,3 +16,3 @@ "defaults",

"dependencies": {
"curriable": "^1.0.0",
"curriable": "^1.2.4",
"pathington": "^1.1.5"

@@ -34,31 +22,29 @@ },

"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/register": "^7.0.0",
"ava": "^1.0.0-beta.8",
"babel-eslint": "^9.0.0",
"babel-loader": "^8.0.0",
"@types/jest": "^23.3.12",
"@types/node": "^10.12.18",
"@types/ramda": "^0.25.45",
"@types/react": "^16.7.18",
"benchmark": "^2.1.4",
"cli-table": "^0.3.1",
"eslint": "^5.4.0",
"eslint-config-rapid7": "^3.0.4",
"eslint-friendly-formatter": "^4.0.1",
"eslint-loader": "^2.1.1",
"eslint": "^5.12.0",
"html-webpack-plugin": "^3.2.0",
"in-publish": "^2.0.0",
"jest": "^23.6.0",
"lodash": "^4.17.10",
"nyc": "^13.0.1",
"optimize-js-plugin": "^0.0.4",
"performance-now": "^2.1.0",
"ramda": "^0.25.0",
"react": "^16.4.1",
"ramda": "^0.26.1",
"react": "^16.7.0",
"react-dom": "^16.4.2",
"rollup": "^0.66.1",
"rollup-plugin-babel": "^4.0.1",
"rollup-plugin-node-resolve": "^3.3.0",
"rollup-plugin-uglify": "^6.0.0",
"sinon": "^6.1.5",
"rollup": "^1.0.2",
"rollup-plugin-babel-minify": "^6.2.0",
"rollup-plugin-node-resolve": "^4.0.0",
"rollup-plugin-typescript2": "^0.18.1",
"ts-jest": "^23.10.4",
"ts-loader": "^5.3.3",
"tslint": "^5.11.0",
"tslint-config-airbnb": "^5.11.0",
"tslint-loader": "^3.5.4",
"typescript": "^3.1.3",
"webpack": "^4.16.5",
"webpack-cli": "^3.1.0",
"webpack-cli": "^3.2.0",
"webpack-dev-server": "^3.1.5"

@@ -72,4 +58,4 @@ },

"homepage": "https://github.com/planttheidea/unchanged#readme",
"main": "lib/index.js",
"module": "es/index.js",
"main": "dist/unchanged.cjs.js",
"module": "dist/unchanged.esm.js",
"name": "unchanged",

@@ -81,23 +67,19 @@ "repository": {

"scripts": {
"benchmark": "npm run transpile:lib && NODE_ENV=production node ./benchmarks/index.js",
"benchmark": "npm run dist && NODE_ENV=production node ./benchmarks/index.js",
"build": "NODE_ENV=production rollup -c",
"clean": "npm run clean:lib && npm run clean:es && npm run clean:dist",
"clean:dist": "rimraf dist",
"clean:lib": "rimraf lib",
"clean:es": "rimraf es",
"dev": "NODE_ENV=development webpack-dev-server --colors --progress --config=webpack/webpack.config.dev.js",
"dist": "npm run clean:dist && npm run build",
"lint": "NODE_ENV=test eslint src",
"lint:fix": "NODE_ENV=test eslint src --fix",
"clean": "rimraf dist",
"dev": "NODE_ENV=development webpack-dev-server --colors --progress --config=webpack/webpack.config.js",
"dist": "npm run clean && npm run build",
"lint": "NODE_ENV=test tslint 'src/*.ts'",
"lint:fix": "npm run lint -- --fix",
"prepublish": "if in-publish; then npm run prepublish:compile; fi",
"prepublish:compile": "npm run lint && npm run test:coverage && npm run transpile:lib && npm run transpile:es && npm run dist",
"prepublish:compile": "npm run lint && npm run test:coverage && npm run dist",
"start": "npm run dev",
"test": "NODE_PATH=. NODE_ENV=production BABEL_ENV=test ava",
"test:coverage": "nyc npm test",
"test:watch": "npm test -- --watch",
"transpile:lib": "npm run clean:lib && BABEL_ENV=lib babel src --out-dir lib",
"transpile:es": "npm run clean:es && BABEL_ENV=es babel src --out-dir es"
"test": "NODE_PATH=. jest",
"test:coverage": "npm run test -- --coverage",
"test:watch": "npm run test -- --watch"
},
"sideEffects": false,
"version": "1.5.2"
"types": "dist/index.d.ts",
"version": "2.0.0"
}
# unchanged
A tiny (~1.9kB minified+gzipped), [fast](https://github.com/planttheidea/unchanged/blob/master/benchmark_results.csv), unopinionated handler for updating JS objects and arrays immutably.
A tiny (~2.0kB minified+gzipped), [fast](https://github.com/planttheidea/unchanged/blob/master/benchmark_results.csv), unopinionated handler for updating JS objects and arrays immutably.
Supports nested key paths via path arrays or [dot-bracket syntax](https://github.com/planttheidea/pathington), and all methods are curriable (with placeholder support) for composability. Can be a drop-in replacement for the `lodash/fp` methods `get`, `set`, `merge`, and `omit` with a 90% smaller footprint.
Supports nested key paths via path arrays or [dotty syntax](https://github.com/planttheidea/pathington), and all methods are curriable (with placeholder support) for composability. Can be a drop-in replacement for the `lodash/fp` methods `get`, `set`, `merge`, and `omit` with a 90% smaller footprint.

@@ -10,3 +10,4 @@ ## Table of contents

- [Usage](#usage)
- [Methods](#methods)
- [Types](#types)
- [Standard methods](#methods)
- [get](#get)

@@ -17,2 +18,3 @@ - [getOr](#getor)

- [has](#has)
- [is](#is)
- [add](#add)

@@ -22,3 +24,13 @@ - [merge](#merge)

- [call](#call)
- [transform](#transform)
- [Transform methods]
- [getWith](#getwith)
- [getWithOr](#getwithor)
- [setWith](#setwith)
- [removeWith](#removewith)
- [hasWith](#haswith)
- [isWith](#iswith)
- [addWith](#addwith)
- [mergeWith](#mergewith)
- [assignWith](#assignwith)
- [callWith](#callwith)
- [Additional objects](#additional-objects)

@@ -35,17 +47,28 @@ - [\_\_](#__)

```javascript
```typescript
import {
__,
add,
addWith,
assign,
assignWith,
call,
callWith,
get,
getWith,
getOr,
getWithOr,
has,
hasWith,
is,
isWith,
merge,
mergeWith,
remove,
removeWith,
set,
transform
setWith
} from "unchanged";
const object = {
const object: unchanged.Unchangeable = {
foo: "foo",

@@ -70,18 +93,48 @@ bar: [

NOTE: There is no `default` export, so if you want to import all methods to a single namespace you should use the `import *` syntax:
**NOTE**: There is no `default` export, so if you want to import all methods to a single namespace you should use the `import *` syntax:
```javascript
```typescript
import * as uc from "unchanged";
```
## Methods
## Types
#### get
This library is both written in, and provided with, types by TypeScript. The internal types used for specific parameters are scoped to the `unchanged` namespace.
`get(path: (Array<number|string>|number|string), object: (Array<any>|Object)): any`
```typescript
// the path used to compute nested locations
type Path = (number | string)[] | number | string;
// the callback used in transform methods
type withHandler = (value: any, ...extraParams: any[]) => any;
// the generic object that is computed upon, either an array or object
interface Unchangeable {
[key: string]: any;
[index: number]: any;
}
```
Notice in the `Unchangeable` interface, there is no reference to symbols. That is because to date, TypeScript does not support Symbols as an index type. If you need to use symbols as object keys, the best workaround I've found is to typecast when it complains:
```typescript
const symbolKey: string = (Symbol("key") as unknown) as string;
const object: { [symbolKey]: string } = {
[symbolKey]: "bar"
};
```
If there is a better alternative for having dynamic Symbol indices, let me know! Happy to accept any PRs from those more experienced in TypeScript than myself.
## Standard methods
### get
```typescript
function get(path: unchanged.Path, object: unchanged.Unchangeable): any;
```
Get the value at the `path` requested on the `object` passed.
```javascript
const object = {
```typescript
const object: unchanged.Unchangeable = {
foo: [

@@ -98,10 +151,16 @@ {

#### getOr
### getOr
`getOr(fallbackValue: any, path: (Array<number|string>|number|string), object: (Array<any>|Object)): any`
```typescript
function getOr(
fallbackValue: any,
path: unchanged.Path,
object: unchanged.Unchangeable
): any;
```
Get the value at the `path` requested on the `object` passed, with a fallback value if that path does not exist.
```javascript
const object = {
```typescript
const object: unchanged.Unchangeable = {
foo: [

@@ -119,10 +178,16 @@ {

#### set
### set
`set(path: (Array<number|string>|number|string), value: any, object: (Array<any>|object)): (Array<any>|Object)`
```typescript
function set(
path: unchanged.Path,
value: any,
object: unchanged.Unchangeable
): unchanged.Unchangeable;
```
Returns a new clone of the `object` passed, with the `value` assigned to the final key on the `path` specified.
Returns a new object based on the `object` passed, with the `value` assigned to the final key on the `path` specified.
```javascript
const object = {
```typescript
const object: unchanged.Unchangeable = {
foo: [

@@ -139,10 +204,15 @@ {

#### remove
### remove
`remove(path: (Array<number|string>|number|string), object: (Array<any>|object)): (Array<any>|Object)`
```typescript
function remove(
path: unchanged.Path,
object: unchanged.Unchangeable
): unchanged.Unchangeable;
```
Returns a new clone of the `object` passed, with the final key on the `path` removed if it exists.
Returns a new object based on the `object` passed, with the final key on the `path` removed if it exists.
```javascript
const object = {
```typescript
const object: unchanged.Unchangeable = {
foo: [

@@ -159,10 +229,12 @@ {

#### has
### has
`has(path: (Array<number|string>|number|string), object: (Array<any>|object)): boolean`
```typescript
function has(path: unchanged.Path, object: unchanged.Unchangeable): boolean;
```
Returns `true` if the object has the path provided, `false` otherwise.
```javascript
const object = {
```typescript
const object: unchanged.Unchangeable = {
foo: [

@@ -180,12 +252,44 @@ {

#### add
### is
`add(path: (Array<number|string>|number|string), value: any, object: (Array<any>|object)): (Array<any>|Object)`
```typescript
function is(
path: unchanged.Path,
value: any,
object: unchanged.Unchangeable
): boolean;
```
Returns a new clone of the `object` passed, with the `value` added at the `path` specified. This can have different behavior depending on whether the item is an `Object` or an `Array`.
Returns `true` if the value at the `path` in `object` is equal to `value` based on [SameValueZero](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#Same-value-zero_equality) equality.
```javascript
const object = {
```typescript
const object: unchanged.Unchangeable = {
foo: [
{
bar: "baz"
}
]
};
console.log(is("foo[0].bar", "baz", object)); // true
console.log(is(["foo", 0, "bar"], "baz", object)); // true
console.log(is("foo[0].bar", "quz', object)); // false
```
### add
```typescript
function add(
path: unchanged.Path,
value: any,
object: unchanged.Unchangeable
): unchanged.Unchangeable;
```
Returns a new object based on the `object` passed, with the `value` added at the `path` specified. This can have different behavior depending on whether the item is an object or an array; objects will simply add / set the key provided, whereas arrays will add a new value to the end.
```typescript
const object: unchanged.Unchangeable = {
foo: [
{
bar: 'baz'

@@ -207,5 +311,5 @@ }

NOTE: If you want to add an item to a top-level array, pass `null` as the key:
**NOTE**: If you want to add an item to a top-level array, pass `null` as the key:
```javascript
```typescript
const object = ["foo"];

@@ -216,27 +320,40 @@

#### merge
### merge
`merge(path: (Array<number|string>|number|string), value: any, object: (Array<any>|object)): (Array<any>|Object)`
```typescript
function merge(
path: unchanged.Path,
value: unchanged.Unchangeable,
object: unchanged.Unchangeable
): unchanged.Unchangeable;
```
Returns a new object that is a deep merge of `value` into `object` at the `path` specified. If you want to perform a shallow merge, see [`assign`](#assign).
```javascript
const object1 = {
oneSpecific: "value",
object: {
```typescript
const object1: unchanged.Unchangeable = {
foo: "bar",
baz: {
one: "value1",
deeply: {
nested: "value",
untouched: true
},
two: "value2"
}
};
const object2 = {
const object2: unchanged.Unchangeable = {
one: "new value",
deeply: {
nested: "other value"
},
three: "value3"
};
console.log(merge("object", object2, object1));
console.log(merge("baz", object2, object1));
/*
{
oneSpecific: 'value',
object: {
one: 'value1',
foo: 'bar',
baz: {
one: 'new value',
deeply: {

@@ -250,11 +367,44 @@ nested: 'other value',

}
```
**NOTE**: If you want to `merge` the entirety of both objects, pass `null` as the key:
```typescript
console.log(merge(null, object2, object1));
/*
{
foo: "bar",
baz: {
one: "value1",
deeply: {
nested: "value",
untouched: true
},
two: "value2"
},
one: "new value",
deeply: {
nested: "other value"
},
three: "value3"
}
*/
```
NOTE: If you want to `merge` the entirety of both objects, pass `null` as the key:
### assign
```javascript
const object1 = {
oneSpecific: "value",
object: {
```typescript
function assign(
path: unchanged.Path,
value: unchanged.Unchangeable,
object: unchanged.Unchangeable
): unchanged.Unchangeable;
```
Returns a new object that is a shallow merge of `value` into `object` at the `path` specified. If you want to perform a deep merge, see [`merge`](#merge).
```typescript
const object1: unchanged.Unchangeable = {
foo: "bar",
baz: {
one: "value1",

@@ -268,3 +418,3 @@ deeply: {

};
const object2 = {
const object2: unchanged.Unchangeable = {
one: "new value",

@@ -277,19 +427,37 @@ deeply: {

console.log(merge(null, object2, object1));
console.log(assign("baz", object2, object1));
/*
{
one: 'new value',
oneSpecific: 'value',
object: {
one: 'value1',
foo: 'bar',
baz: {
one: 'new value',
deeply: {
nested: 'value',
untouched: true,
nested: 'other value',
},
two: 'value2',
three: 'value3
}
}
```
**NOTE**: If you want to `assign` the entirety of both objects, pass `null` as the key:
```typescript
console.log(assign(null, object2, object1));
/*
{
foo: "bar",
baz: {
one: "value1",
deeply: {
nested: "value",
untouched: true
},
two: "value2"
},
one: "new value",
deeply: {
nested: 'other value',
nested: "other value"
},
three: 'value3
three: "value3"
}

@@ -299,16 +467,300 @@ */

#### assign
### call
`assign(path: (Array<number|string>|number|string), value: any, object: (Array<any>|object)): (Array<any>|Object)`
```typescript
function call(
path: unchanged.Path,
parameters: any[],
object: unchanged.Unchangeable,
context?: any = object
): any;
```
Returns a new object that is a shallow merge of `value` into `object` at the `path` specified. If you want to perform a deep merge, see [`merge`](#merge).
Call the method at the `path` requested on the `object` passed, and return what it's call returns.
```javascript
const object1 = {
oneSpecific: "value",
object: {
```typescript
const object: unchanged.Unchangeable = {
foo: [
{
bar(a, b) {
return a + b;
}
}
]
};
console.log(call("foo[0].bar", [1, 2], object)); // 3
console.log(call(["foo", 0, "bar"], [1, 2], object)); // 3
```
You can also provide an optional fourth parameter of `context`, which will be the `this` value in the method call. This will default to the `object` itself.
```typescript
const object: unchanged.Unchangeable = {
calculate: true,
foo: [
{
bar(a, b) {
return this.calculate ? a + b : 0;
}
}
]
};
console.log(call("foo[0].bar", [1, 2], object)); // 3
console.log(call("foo[0].bar", [1, 2], object, {})); // 0
```
**NOTE**: Because `context` is optional, it cannot be independently curried; you must apply it in the call when the `object` is passed.
## Transform methods
Each standard method has it's own related `With` method, which accepts a callback `fn` as the first curried parameter. In most cases this callback serves as a transformer for the value retrieved, set, merged, etc.; the exception is `removeWith`, where the callback serves as a validator as to whether to remove or not.
The signature of all callbacks is the `withHandler` specified in [`Types`](#types). Because `extraParams` are optional parameters, they cannot be independently curried; you must apply them in the call when the `object` is passed.
### getWith
```typescript
function getWith(
fn: unchanged.withHandler,
path: unchanged.Path,
object: unchanged.Unchangeable,
...extraParams?: any[]
): any;
```
Get the return value of `fn` based on the value at the `path` requested on the `object` passed. `fn` is called with the current value at the `path` as the first parameter, and any additional parameters passed as `extraParams` following that.
```typescript
const object: unchanged.Unchangeable = {
foo: [
{
bar: "baz"
}
]
};
const fn: unchanged.withHandler = (value: any, nullValue: any): any =>
currentValue === nullValue ? null : currentValue;
console.log(getWith(fn, "foo[0].bar", object)); // 'baz'
console.log(getWith(fn, "foo[0].bar", object, "baz")); // null
console.log(getWith(fn, ["foo", 0, "bar"], object)); // 'baz'
console.log(getWith(fn, ["foo", 0, "bar"], object, "baz")); // null
```
### getWithOr
```typescript
function getWithOr(
fn: unchanged.withHandler,
fallbackValue: any,
path: unchanged.Path,
object: unchanged.Unchangeable,
...extraParams?: any[]
): any;
```
Get the return value of `fn` based on the value at the `path` requested on the `object` passed, falling back to `fallbackValue` when no match is found at `path`. When a match is found, `fn` is called with the current value at the `path` as the first parameter, and any additional parameters passed as `extraParams` following that.
```typescript
const object: unchanged.Unchangeable = {
foo: [
{
bar: "baz"
}
]
};
const fn: unchanged.withHandler = (value: any, nullValue: any): any =>
currentValue === nullValue ? null : currentValue;
console.log(getWithOr(fn, "quz", "foo[0].bar", object)); // 'baz'
console.log(getWithOr(fn, "quz", "foo[0].bar", object, "baz")); // null
console.log(getWithOr(fn, "quz", "foo[0].notFound", object, "baz")); // 'quz'
console.log(getWithOr(fn, "quz", ["foo", 0, "bar"], object)); // 'baz'
console.log(getWithOr(fn, "quz", ["foo", 0, "bar"], object, "baz")); // null
console.log(getWithOr(fn, "quz", ["foo", 0, "notFound"], object, "baz")); // 'quz'
```
### setWith
```typescript
function setWith(
fn: unchanged.withHandler,
path: unchanged.Path,
object: unchanged.Unchangeable,
...extraParams?: any[]
): unchanged.Unchangeable;
```
Returns a new object based on the `object` passed, with the return value of `fn` assigned to the final key on the `path` specified. `fn` is called with the current value at the `path` as the first parameter, and any additional parameters passed as `extraParams` following that.
```typescript
const object: unchanged.Unchangeable = {
foo: [
{
bar: "baz"
}
]
};
const fn: unchanged.withHandler = (value: any, preventUpdate: boolean): any =>
preventUpdate ? currentValue : "quz";
console.log(setWith(fn, "foo[0].bar", object)); // {foo: [{bar: 'quz'}]}
console.log(setWith(fn, "foo[0].bar", object, true)); // {foo: [{bar: 'baz'}]}
console.log(setWith(fn, ["foo", 0, "bar"], object)); // {foo: [{bar: 'quz'}]}
console.log(setWith(fn, ["foo", 0, "bar"], object, true)); // {foo: [{bar: 'baz'}]}
```
### removeWith
```typescript
function removeWith(
fn: unchanged.withHandler,
path: unchanged.Path,
object: unchanged.Unchangeable,
...extraParams?: any[]
): unchanged.Unchangeable;
```
Returns a new object based on the `object` passed, with the final key on the `path` removed if it exists and the return from `fn` is truthy.
```typescript
const object: unchanged.Unchangeable = {
foo: [
{
bar: "baz"
}
]
};
const fn: unchanged.withHandler = (
value: any,
shouldNotRemove: boolean
): boolean => !shouldNotRemove && value === "baz";
console.log(removeWith(fn, "foo[0].bar", object)); // {foo: [{}]}
console.log(removeWith(fn, "foo[0].bar", object, true)); // {foo: [{bar: 'baz'}]}
console.log(removeWith([fn, "foo", 0, "bar"], object)); // {foo: [{}]}
console.log(removeWith([fn, "foo", 0, "bar"], object, true)); // {foo: [{bar: 'baz'}]}
```
### hasWith
```typescript
function hasWith(
fn: unchanged.withHandler,
path: unchanged.Path,
object: unchanged.Unchangeable,
...extraParams?: any[]
): boolean;
```
Returns `true` if the return value of `fn` based on the value returned from `path` in the `object` returns truthy, `false` otherwise.
```typescript
const object: unchanged.Unchangeable = {
foo: [
{
bar: "baz"
}
]
};
const fn: unchanged.withHandler = (
value: any,
shouldBeNull: boolean
): boolean => (shouldBeNull ? value === null : value === "baz");
console.log(hasWith(fn, "foo[0].bar", object)); // true
console.log(hasWith(fn, "foo[0].bar", object, true)); // false
console.log(hasWith(fn, ["foo", 0, "bar"], object)); // true
console.log(hasWith(fn, ["foo", 0, "bar"], object, true)); // false
console.log(hasWith(fn, "bar", object)); // false
```
### isWith
```typescript
function isWith(
fn: unchanged.withHandler,
path: unchanged.Path,
object: unchanged.Unchangeable
): boolean;
```
Returns `true` if the return value of `fn` based on the value returned from `path` in the `object` is equal to `value` based on [SameValueZero](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#Same-value-zero_equality) equality.
```typescript
const object: unchanged.Unchangeable = {
foo: [
{
bar: "baz",
quz: "not baz"
}
]
};
const fn: unchanged.withHandler = (value: any): number =>
value && value.length === 3;
console.log(isWith(fn, "foo[0].bar", object)); // true
console.log(isWith(fn, ["foo", 0, "bar"], object)); // true
console.log(isWith(fn, "foo[0].quz", object)); // false
```
### addWith
```typescript
function addWith(
fn: unchanged.withHandler,
path: unchanged.Path,
object: unchanged.Unchangeable
): unchanged.Unchangeable;
```
Returns a new object based on the `object` passed, with the return value of `fn` added at the `path` specified. This can have different behavior depending on whether the item is an object or an array; objects will simply add / set the key provided, whereas arrays will add a new value to the end.
```typescript
const object: unchanged.Unchangeable = {
foo: [
{
bar: "baz"
}
]
};
const fn: unchanged.withHandler = (value: any) =>
value
? value
.split("")
.reverse()
.join("")
: "new value";
// object
console.log(addWith(fn, "foo", object)); // {foo: [{bar: 'baz'}, 'new value']}
console.log(addWith(fn, ["foo"], object)); // {foo: [{bar: 'baz'}, 'new value']}
// array
console.log(addWith(fn, "foo[0].bar", object)); // {foo: [{bar: 'zab'}]}
console.log(addWith(fn, ["foo", 0, "bar"], object)); // {foo: [{bar: 'zab''}]}
```
### mergeWith
```typescript
function mergeWith(
fn: unchanged.withHandler,
path: unchanged.Path,
object: unchanged.Unchangeable
): unchanged.Unchangeable;
```
Returns a new object that is a deep merge of the return value of `fn` into `object` at the `path` specified if a valid mergeable object, else returns the original object. If you want to perform a shallow merge, see [`assignWith`](#assignwith).
```typescript
const object1: unchanged.Unchangeable = {
foo: "bar",
baz: {
one: "value1",
deeply: {
nested: "value",
untouched: false
untouched: true
},

@@ -318,3 +770,3 @@ two: "value2"

};
const object2 = {
const object2: unchanged.Unchangeable = {
one: "new value",

@@ -326,11 +778,14 @@ deeply: {

};
const fn: unchanged.withHandler = (value: any) =>
value && value.one === "value1" ? object2 : null;
console.log(assign("object", object2, object1));
console.log(mergeWith(fn, "baz", object1));
/*
{
oneSpecific: 'value',
object: {
one: 'value1',
foo: 'bar',
baz: {
one: 'new value',
deeply: {
nested: 'other value',
untouched: true,
},

@@ -342,10 +797,27 @@ two: 'value2',

*/
console.log(mergeWith(fn, "baz.deeply", object1));
/*
// untouched object1
{
foo: "bar",
baz: {
one: "value1",
deeply: {
nested: 'value',
untouched: true,
},
two: "value2"
}
}
*/
```
NOTE: If you want to `assign` the entirety of both objects, pass `null` as the key:
**NOTE**: If you want to `merge` the entirety of both objects, pass `null` as the key:
```javascript
const object1 = {
oneSpecific: "value",
object: {
```typescript
console.log(mergeWith(fn, null, object1));
/*
{
foo: "bar",
baz: {
one: "value1",

@@ -357,5 +829,37 @@ deeply: {

two: "value2"
},
one: "new value",
deeply: {
nested: "other value"
},
three: "value3"
}
*/
```
### assignWith
```typescript
function assignWith(
fn: unchanged.withHandler,
path: unchanged.Path,
object: unchanged.Unchangeable
): unchanged.Unchangeable;
```
Returns a new object that is a shallow merge of the return value of `fn` into `object` at the `path` specified if a valid mergeable object, else returns the original object. If you want to perform a deep merge, see [`mergeWith`](#mergeWith).
```typescript
const object1: unchanged.Unchangeable = {
foo: "bar",
baz: {
one: "value1",
deeply: {
nested: "value",
untouched: true
},
two: "value2"
}
};
const object2 = {
const object2: unchanged.Unchangeable = {
one: "new value",

@@ -367,20 +871,32 @@ deeply: {

};
const fn: unchanged.withHandler = (value: any) =>
value && value.one === "value1" ? object2 : null;
console.log(assign(null, object2, object1));
console.log(assignWith(fn, "baz", object1));
/*
{
one: 'new value',
oneSpecific: 'value',
object: {
one: 'value1',
foo: 'bar',
baz: {
one: 'new value',
deeply: {
nested: 'other value',
},
two: 'value2',
three: 'value3
}
}
*/
console.log(assignWith(fn, "baz.deeply", object1));
/*
// untouched object1
{
foo: "bar",
baz: {
one: "value1",
deeply: {
nested: 'value',
untouched: true,
},
two: 'value2',
},
deeply: {
nested: 'other value',
},
three: 'value3
two: "value2"
}
}

@@ -390,10 +906,17 @@ */

#### call
### callWith
`call(path: (Array<number|string>|number|string), parameters: Array<any>, object: (Array<any>|Object)[, context: any])`
```typescript
function callWith(
path: unchanged.Path,
parameters: any[],
object: unchanged.Unchangeable,
context?: any = object
): any;
```
Call the method at the `path` requested on the `object` passed, and return what it's call returns.
Call the method returned from `fn` based on the `path` specified on the `object`, and if a function return what it's call returns.
```javascript
const object = {
```typescript
const object: unchanged.Unchangeable = {
foo: [

@@ -407,5 +930,11 @@ {

};
const fn: unchanged.withHandler = (value: any): any =>
typeof value === fn
? fn
: () =>
console.error("Error: Requested call of a method that does not exist.");
console.log(call("foo[0].bar", [1, 2], object)); // 3
console.log(call(["foo", 0, "bar"], [1, 2], object)); // 3
console.log(callWith(fn, "foo[0].bar", [1, 2], object)); // 3
console.log(callWith(fn, ["foo", 0, "bar"], [1, 2], object)); // 3
callWith(fn, "foo[1].nope", object); // Error: Requested call of a method that does not exist.
```

@@ -415,4 +944,4 @@

```javascript
const object = {
```typescript
const object: unchanged.Unchangeable = {
calculate: true,

@@ -427,41 +956,21 @@ foo: [

};
const fn: unchanged.withHandler = (value: any): any =>
typeof value === fn
? fn
: () =>
console.error("Error: Requested call of a method that does not exist.");
console.log(call("foo[0].bar", [1, 2], object)); // 3
console.log(call("foo[0].bar", [1, 2], object, {})); // 0
console.log(callWith(fn, "foo[0].bar", [1, 2], object)); // 3
console.log(callWith(fn, "foo[0].bar", [1, 2], object, {})); // 0
```
**NOTE**: Because `context` is an optional parameter, it cannot be independently curried; you must apply it in the call when the `object` is passed.
**NOTE**: Because `context` is optional, it cannot be independently curried; you must apply it in the call when the `object` is passed.
#### transform
`transform(path: (Array<number|string>|number|string), fn: function, object: (Array<any>|object)[, ...extraParams: Array<any>]): (Array<any>|Object)`
Returns a new clone of the `object` passed, with the return value of `fn` assigned to the final key on the `path` specified. `fn` is called with the current value at the `path` as the first parameter, and any additional parameters passed as `extraParams` following that.
```javascript
const object = {
foo: [
{
bar: "baz"
}
]
};
const fn = (currentValue, preventUpdate) =>
preventUpdate ? currentValue : "quz";
console.log(transform("foo[0].bar", fn, object)); // {foo: [{bar: 'quz'}]}
console.log(transform("foo[0].bar", fn, object, true)); // {foo: [{bar: 'baz'}]}
console.log(transform(["foo", 0, "bar"], fn, object)); // {foo: [{bar: 'quz'}]}
console.log(transform(["foo", 0, "bar"], fn, object, true)); // {foo: [{bar: 'baz'}]}
```
**NOTE**: Because `extraParams` are optional parameters, they cannot be independently curried; you must apply them in the call when the `object` is passed.
## Additional objects
#### \_\_
### \_\_
A placeholder value used to identify "gaps" in a curried function, allowing for earlier application of arguments later in the argument order.
```javascript
```typescript
import {__, set} from 'unchanged';

@@ -480,6 +989,7 @@

#### lodash
### lodash
[`lodash/fp`](https://lodash.com/) (the functional programming implementation of `lodash`) is identical in implementation to `unchanged`'s methods, just with a _10.5x_ larger footprint. These methods should map directly:
- _lodash_ => _unchanged_
- `curry.placeholder` => `__`

@@ -490,13 +1000,21 @@ - `get` => `get`

- `omit` => `remove`
- `set` => `set` (also maps to `add` for objects only)
- `set` => `set`
NOTE: There is no direct parallel for the `add` method in `lodash/fp`; the closest is `concat` but that is array-specific and does not support nested keys.
### ramda
#### ramda
[`ramda`](http://ramdajs.com/) is similar in its implementation, however the first big difference is that dot-bracket syntax is not supported by `ramda`, only path arrays. The related methods are:
[`ramda`](http://ramdajs.com/) is similar in its implementation, however the first big difference is that dot-bracket syntax is not supported by `ramda`, only path arrays. Another difference is that the `ramda` methods that clone objects (`assocPath`, for example) only work with objects; arrays are implicitly converted into objects, which can make updating collections challenging.
- _ramda_ => _unchanged_
- `__` => `__`
- `path` => `get`
- `pathOr` => `getOr`
- `merge` => `merge`
- `omit` => `remove`
- `assocPath` => `set`
Another difference is that the `ramda` methods that clone objects (`assocPath`, for example) only work with objects; arrays are implicitly converted into objects, which can make updating collections challenging.
The last main difference is the way that objects are copied, example:
```javascript
```typescript
function Foo(value) {

@@ -527,3 +1045,3 @@ this.value = value;

#### Other immutability libraries
### Other immutability libraries

@@ -547,14 +1065,13 @@ This includes popular solutions like [Immutable.js](https://facebook.github.io/immutable-js/), [seamless-immutable](https://github.com/rtfeldman/seamless-immutable), [mori](http://swannodette.github.io/mori/), etc. These solutions all work well, but with one caveat: _you need to buy completely into their system_. Each of these libraries redefines how the objects are stored internally, and require that you learn a new, highly specific API to use these custom objects. `unchanged` is unopinionated, accepting standard JS objects and returning standard JS objects, no transformation or learning curve required.

- `build` => run webpack to build development `dist` file with NODE_ENV=development
- `build:minified` => run webpack to build production `dist` file with NODE_ENV=production
- `benchmark` => run benchmark suite comparing top-level and deeply-nested `get` and `set` operations with `lodash` and `ramda`
- `build` => run `rollup` to build `dist` files for CommonJS, ESM, and UMD consumers
- `clean` => run `rimraf` on the `dist` folder
- `dev` => run webpack dev server to run example app / playground
- `dist` => runs `build` and `build:minified`
- `dist` => runs `clean` and `build`
- `lint` => run ESLint against all files in the `src` folder
- `lint:fix` => run `lint` with autofixing applied
- `prepublish` => runs `prepublish:compile` when publishing
- `prepublish:compile` => run `lint`, `test:coverage`, `transpile:es`, `transpile:lib`, `dist`
- `prepublish:compile` => run `lint`, `test:coverage`, `dist`
- `test` => run AVA test functions with `NODE_ENV=test`
- `test:coverage` => run `test` but with `nyc` for coverage checker
- `test:watch` => run `test`, but with persistent watcher
- `transpile:lib` => run babel against all files in `src` to create files in `lib`
- `transpile:es` => run babel against all files in `src` to create files in `es`, preserving ES2015 modules (for
[`pkg.module`](https://github.com/rollup/rollup/wiki/pkg.module))

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc