Created
October 28, 2015 21:45
-
-
Save nelix/c23841692d7bb8cbafb7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const merge = (obj, src) => { | |
let res = obj; | |
for (let k of Object.keys(src)) { | |
if (res[k] === src[k]) { | |
continue; | |
} | |
if (typeof src[k] === 'object' && src[k] !== null && src[k].constructor === Object) { | |
let sub = res[k]; | |
if (typeof sub !== 'object' || sub === null || sub.constructor !== Object) { | |
sub = {}; | |
} | |
const out = merge(sub, src[k]); | |
if (out === res[k]) { | |
continue; | |
} | |
if (res === obj) { | |
res = Object.assign({}, obj); | |
} | |
res[k] = out; | |
} else { | |
if (res === obj) { | |
res = Object.assign({}, obj); | |
} | |
res[k] = src[k]; | |
} | |
} | |
return res; | |
}; | |
const append = (arr, ...e) => (arr || []).concat(e); | |
const clone = obj => (obj === undefined) ? obj : JSON.parse(JSON.stringify(obj)); | |
const extract = (obj, props) => props.reduce((res, keyOrPair) => { | |
if (typeof keyOrPair === 'string') { | |
if (Object.hasOwnProperty.call(obj, keyOrPair)) { | |
res[keyOrPair] = obj[keyOrPair]; | |
} | |
} else if (Array.isArray(keyOrPair)) { | |
let [key, fn] = keyOrPair; | |
let v = fn(obj[key], obj); | |
if (typeof v !== 'undefined') { | |
res[key] = v; | |
} | |
} | |
return res; | |
}, {}); | |
const ifArray = fn => (value, obj) => Array.isArray(value) ? fn(value, obj) : undefined; | |
const ifNumber = fn => (value, obj) => (typeof value === 'number') ? fn(value, obj) : undefined; | |
const ifNotNull = fn => (value, obj) => (value !== null) ? fn(value, obj) : undefined; | |
const addPrefix = prefix => value => `${prefix}${value}`; | |
const mapPrefix = prefix => arr => arr.map(addPrefix(prefix)); | |
const getIn = (obj, path, notSetValue) => { | |
let r = obj || {}; | |
for (let k of path) { | |
if (typeof r !== 'object' || r === null || r.constructor !== Object) { | |
throw new Error(`encountered non-object value at ${k} via ${path.join('.')}`); | |
} | |
r = r[k]; | |
} | |
return r === 'undefined' ? notSetValue : r; | |
}; | |
const updateIn = (obj, path, notSetValue, updater) => { | |
if (typeof obj !== 'object' || obj === null || obj.constructor !== Object) { | |
throw new Error(`encountered non-object`); | |
} | |
let r = null; | |
if (path.length === 1) { | |
if (typeof obj[path[0]] === 'undefined') { | |
r = updater(notSetValue); | |
} else { | |
r = updater(obj[path[0]]); | |
} | |
} else { | |
if (typeof obj[path[0]] === 'undefined') { | |
r = updateIn({}, path.slice(1), notSetValue, updater) | |
} else { | |
r = updateIn(obj[path[0]], path.slice(1), notSetValue, updater) | |
} | |
} | |
if (r === obj[path[0]]) { | |
return obj; | |
} | |
return Object.assign({}, obj, { | |
[path[0]]: r, | |
}); | |
}; | |
const setIn = (obj, path, value) => { | |
return updateIn(obj, path, null, () => value); | |
}; | |
const mergeIn = (obj, path, data) => { | |
return updateIn(obj, path, {}, (value) => merge(value, data)); | |
}; | |
const addToSet = (arr, ...e) => e.reduce((a, v) => { | |
return a.indexOf(v) === -1 ? append(a, v) : a; | |
}, arr); | |
export default { | |
addPrefix, | |
addToSet, | |
append, | |
clone, | |
extract, | |
getIn, | |
ifArray, | |
ifNotNull, | |
ifNumber, | |
mapPrefix, | |
merge, | |
mergeIn, | |
setIn, | |
updateIn, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment