Skip to content

Instantly share code, notes, and snippets.

@nelix
Created October 28, 2015 21:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nelix/c23841692d7bb8cbafb7 to your computer and use it in GitHub Desktop.
Save nelix/c23841692d7bb8cbafb7 to your computer and use it in GitHub Desktop.
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