UNPKG

@dot-event/store

Version:
175 lines (152 loc) 3.93 kB
/* eslint-disable max-len, sort-keys */ /*prettier-ignore*/ "use strict"; /** * Set a value by a dot path. * @param obj The object to evaluate. * @param prop The path to be set. * @param val The value to set. */ function set(obj, prop, value) { prop = propToArray(prop) var setPropImmutableRec = function(obj, prop, value, i) { var clone, head = prop[i] if (prop.length > i) { if (Array.isArray(obj)) { head = getArrayIndex(head, obj) clone = obj.slice() } else { clone = Object.assign({}, obj) } clone[head] = setPropImmutableRec( obj[head] !== undefined ? obj[head] : {}, prop, value, i + 1 ) return clone } return typeof value === "function" ? value(obj) : value } return setPropImmutableRec(obj, prop, value, 0) } /** * Get a value by a dot path. * @param obj The object to evaluate. * @param prop The path to value that should be returned. */ function get(obj, prop, value) { prop = propToArray(prop) for (var i = 0; i < prop.length; i++) { if (typeof obj !== "object") { return value } var head = prop[i] if (Array.isArray(obj) && head === "$end") { head = obj.length - 1 } obj = obj[head] } if (typeof obj === "undefined") { return value } return obj } /** * Delete a property by a dot path. * If target container is an object, the property is deleted. * If target container is an array, the index is deleted. * If target container is undefined, nothing is deleted. * @param obj The object to evaluate. * @param prop The path to the property or index that should be deleted. */ function _delete(obj, prop) { prop = propToArray(prop) var deletePropImmutableRec = function(obj, prop, i) { var clone, head = prop[i] if ( typeof obj !== "object" || (!Array.isArray(obj) && obj[head] === undefined) ) { return obj } if (prop.length - 1 > i) { if (Array.isArray(obj)) { head = getArrayIndex(head, obj) clone = obj.slice() } else { clone = Object.assign({}, obj) } clone[head] = deletePropImmutableRec( obj[head], prop, i + 1 ) return clone } if (Array.isArray(obj)) { head = getArrayIndex(head, obj) clone = [].concat( obj.slice(0, head), obj.slice(head + 1) ) } else { clone = Object.assign({}, obj) delete clone[head] } return clone } return deletePropImmutableRec(obj, prop, 0) } /** * Merges a value. The target value must be an object, array, null, or undefined. * If target is an object, Object.assign({}, target, param) is used. * If target an array, target.concat(param) is used. * If target is null or undefined, the value is simply set. * @param obj The object to evaluate. * @param prop The path to the value. * @param val The value to merge into the target value. */ function merge(obj, prop, val) { var curVal = get(obj, prop) if (typeof curVal === "object") { if (Array.isArray(curVal)) { return set(obj, prop, curVal.concat(val)) } else if (curVal === null) { return set(obj, prop, val) } else { var merged = Object.assign({}, curVal, val) return set(obj, prop, merged) } } else if (typeof curVal === "undefined") { return set(obj, prop, val) } else { return obj } } function getArrayIndex(head, obj) { if (head === "$end") { head = Math.max(obj.length - 1, 0) } if (!/^\+?\d+$/.test(head)) { throw new Error( "Array index '" + head + "' has to be an integer" ) } return parseInt(head) } function propToArray(prop) { if (Array.isArray(prop)) { return prop } return prop.split(".") } module.exports = { delete: _delete, get: get, merge: merge, propToArray: propToArray, set: set, }