Spaces:
Paused
Paused
| module.exports = flatten | |
| flatten.flatten = flatten | |
| flatten.unflatten = unflatten | |
| function isBuffer (obj) { | |
| return obj && | |
| obj.constructor && | |
| (typeof obj.constructor.isBuffer === 'function') && | |
| obj.constructor.isBuffer(obj) | |
| } | |
| function keyIdentity (key) { | |
| return key | |
| } | |
| function flatten (target, opts) { | |
| opts = opts || {} | |
| const delimiter = opts.delimiter || '.' | |
| const maxDepth = opts.maxDepth | |
| const transformKey = opts.transformKey || keyIdentity | |
| const output = {} | |
| function step (object, prev, currentDepth) { | |
| currentDepth = currentDepth || 1 | |
| Object.keys(object).forEach(function (key) { | |
| const value = object[key] | |
| const isarray = opts.safe && Array.isArray(value) | |
| const type = Object.prototype.toString.call(value) | |
| const isbuffer = isBuffer(value) | |
| const isobject = ( | |
| type === '[object Object]' || | |
| type === '[object Array]' | |
| ) | |
| const newKey = prev | |
| ? prev + delimiter + transformKey(key) | |
| : transformKey(key) | |
| if (!isarray && !isbuffer && isobject && Object.keys(value).length && | |
| (!opts.maxDepth || currentDepth < maxDepth)) { | |
| return step(value, newKey, currentDepth + 1) | |
| } | |
| output[newKey] = value | |
| }) | |
| } | |
| step(target) | |
| return output | |
| } | |
| function unflatten (target, opts) { | |
| opts = opts || {} | |
| const delimiter = opts.delimiter || '.' | |
| const overwrite = opts.overwrite || false | |
| const transformKey = opts.transformKey || keyIdentity | |
| const result = {} | |
| const isbuffer = isBuffer(target) | |
| if (isbuffer || Object.prototype.toString.call(target) !== '[object Object]') { | |
| return target | |
| } | |
| // safely ensure that the key is | |
| // an integer. | |
| function getkey (key) { | |
| const parsedKey = Number(key) | |
| return ( | |
| isNaN(parsedKey) || | |
| key.indexOf('.') !== -1 || | |
| opts.object | |
| ) ? key | |
| : parsedKey | |
| } | |
| function addKeys (keyPrefix, recipient, target) { | |
| return Object.keys(target).reduce(function (result, key) { | |
| result[keyPrefix + delimiter + key] = target[key] | |
| return result | |
| }, recipient) | |
| } | |
| function isEmpty (val) { | |
| const type = Object.prototype.toString.call(val) | |
| const isArray = type === '[object Array]' | |
| const isObject = type === '[object Object]' | |
| if (!val) { | |
| return true | |
| } else if (isArray) { | |
| return !val.length | |
| } else if (isObject) { | |
| return !Object.keys(val).length | |
| } | |
| } | |
| target = Object.keys(target).reduce(function (result, key) { | |
| const type = Object.prototype.toString.call(target[key]) | |
| const isObject = (type === '[object Object]' || type === '[object Array]') | |
| if (!isObject || isEmpty(target[key])) { | |
| result[key] = target[key] | |
| return result | |
| } else { | |
| return addKeys( | |
| key, | |
| result, | |
| flatten(target[key], opts) | |
| ) | |
| } | |
| }, {}) | |
| Object.keys(target).forEach(function (key) { | |
| const split = key.split(delimiter).map(transformKey) | |
| let key1 = getkey(split.shift()) | |
| let key2 = getkey(split[0]) | |
| let recipient = result | |
| while (key2 !== undefined) { | |
| if (key1 === '__proto__') { | |
| return | |
| } | |
| const type = Object.prototype.toString.call(recipient[key1]) | |
| const isobject = ( | |
| type === '[object Object]' || | |
| type === '[object Array]' | |
| ) | |
| // do not write over falsey, non-undefined values if overwrite is false | |
| if (!overwrite && !isobject && typeof recipient[key1] !== 'undefined') { | |
| return | |
| } | |
| if ((overwrite && !isobject) || (!overwrite && recipient[key1] == null)) { | |
| recipient[key1] = ( | |
| typeof key2 === 'number' && | |
| !opts.object ? [] : {} | |
| ) | |
| } | |
| recipient = recipient[key1] | |
| if (split.length > 0) { | |
| key1 = getkey(split.shift()) | |
| key2 = getkey(split[0]) | |
| } | |
| } | |
| // unflatten again for 'messy objects' | |
| recipient[key1] = unflatten(target[key], opts) | |
| }) | |
| return result | |
| } | |