1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- function copyWith (obj, key, value) {
- const result = typeof key === 'number' ? obj == null ? [] : [...obj] : obj == null ? {} : {...obj};
- result[key] = value;
- return result;
- }
- const constructKeys = function (keyDescriptions) {
- const keys = [];
- function fillKeys (keyDescriptions) {
- keyDescriptions.forEach(each => {
- if (typeof each === 'number') keys.push(each);
- else if (Array.isArray(each)) fillKeys(each);
- else keys.push(...each.toString().split('.'));
- });
- }
- fillKeys(keyDescriptions);
- return keys;
- };
- const deepGet = (keys, obj) => keys.reduce((x, key) => x == null ? undefined : x[key], obj);
- const deepPut = (keys, obj, val) => {
- function setVal (x, index) {
- if (index >= keys.length) return val;
- const key = keys[index],
- value = x == null ? undefined : x[key],
- modified = setVal(value, index + 1);
- return value === modified ? x : copyWith(x, key, modified);
- }
- return setVal(obj, 0);
- };
- export const deepGetOrNil = (...keyDescriptions) => {
- const keys = constructKeys(keyDescriptions);
- return obj => deepGet(keys, obj);
- };
- export const deget = deepGetOrNil;
- export const deepCopyOnWrite = (...keyDescriptions) => {
- const keys = constructKeys(keyDescriptions);
- return val => obj => deepPut(keys, obj, val);
- };
- export const decow = deepCopyOnWrite;
- export const cowValueModel = (...keyDescriptions) => {
- const keys = constructKeys(keyDescriptions);
- const GET_SENTINEL = {};
- return (obj, val = GET_SENTINEL) =>
- val === GET_SENTINEL ?
- deepGet(keys, obj) :
- deepPut(keys, obj, val);
- };
- export const cowWorkshop = (keys, fn = x => x) => (obj, {result = obj, resultKeys = keys, diff} = {}) => {
- keys.forEach((key, index) => {
- const value = fn(deget(key)(obj));
- if (typeof value === "undefined") return;
- const modifier = decow(resultKeys[index])(value);
- const oldResult = result;
- result = modifier(oldResult);
- if (result !== oldResult) {
- diff = modifier(diff);
- }
- });
- return {result, diff};
- };
|