export const eq = (a, b) => { if (a === b) { return true; } if (a === null || b === null) { return false; } if (typeof a != "object" || typeof b != "object") { return false; } if (Array.isArray(a) !== Array.isArray(b)) { return false; } if (Object.keys(a).length !== Object.keys(b).length) { return false; } for (const k in a) { if (!b.hasOwnProperty(k)) { return false; } if (!eq(a[k], b[k])) { return false; } } return true; }; export const keys = (ks, obj) => ks.reduce( (ret, k) => obj.hasOwnProperty(k) ? {...ret, [k]: obj[k]} : ret, {}, ); export const difference = (a, b) => { const diff = new Set(a); for (const el of b) { diff.delete(el); } return diff; }; export const assocIn = (obj, path, value) => path.length === 0 ? obj : path.length === 1 ? { ...obj, [path[0]]: value } : { ...obj, [path[0]]: assocIn( (obj[path[0]] || {}), path.slice(1), value ) }; export const getIn = (obj, path) => path.length === 0 ? obj : getIn(obj?.[path[0]], path.slice(1)); export const first = (arr, fn) => { for (const x of arr) { const ret = fn(x); if (ret) { return ret; } } return null; }; export const promisify = fn => (...args) => new Promise((resolve, reject) => fn(...args, (err, data) => err ? reject(err) : resolve(data)));