123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- const copyArrayWith = (key, value) => obj => {
- const result = obj == null ? [] : [...obj];
- result[key] = value;
- return result;
- };
- const copyMapWith = (key, value) => obj => {
- const result = obj == null ? new Map() : new Map(obj);
- result.set(key, value);
- return result;
- };
- const copyObjectWith = (key, value) => obj => {
- const result = obj == null ? {} : {...obj};
- result[key] = value;
- return result;
- };
- const isMapKey = key => typeof key === 'object' && key.isKeyInMap === true;
- export const keyInMap = key => ({isKeyInMap: true, key});
- export const kim = keyInMap;
- const copyWith = (key, value) =>
- typeof key === 'number' ? copyArrayWith(key, value) :
- isMapKey(key) ? copyMapWith(key.key, value) :
- copyObjectWith(key, value);
- const constructKeys = function (keyDescriptions) {
- const keys = [];
- function fillKeys (keyDescriptions) {
- keyDescriptions.forEach(each => {
- if (typeof each === 'number' || isMapKey(each)) keys.push(each);
- else if (Array.isArray(each)) fillKeys(each);
- else keys.push(...each.toString().split('.'));
- });
- }
- fillKeys(keyDescriptions);
- return keys;
- };
- const getKey = (x, key) => x == null ? undefined : isMapKey(key) ? x.get(key.key) : x[key];
- const getKeyWithCheck = (x, key) =>
- x == null ? null :
- isMapKey(key) ? x.has(key.key) ? {value: x.get(key.key)} : null :
- x.hasOwnProperty(key) ? {value: x[key]} : null;
- export const deepGetOrNil = (...keyDescriptions) => {
- const keys = constructKeys(keyDescriptions);
- return obj => keys.reduce(getKey, obj);
- };
- export const deget = deepGetOrNil;
- const chain = (list, stop, step) => (function worker (index) {
- return index >= list.length ? stop : step(list[index], worker(index + 1));
- })(0);
- const copyOnModification = (obj, key, value, modifierFn) => {
- const modified = modifierFn(value);
- return value === modified ? obj : copyWith(key, modified)(obj);
- };
- export const deepCopyOnWrite = (...keyDescriptions) => {
- const keys = constructKeys(keyDescriptions);
- return val => chain(keys, () => val, (key, next) => x =>
- copyOnModification(x, key, getKey(x, key), next)
- );
- };
- export const decow = deepCopyOnWrite;
- export const deepCopyOnMap = (...keyDescriptions) => {
- const keys = constructKeys(keyDescriptions);
- return fn => chain(keys, fn, (key, next) => x => {
- const valueWithCheck = getKeyWithCheck(x, key);
- if (valueWithCheck == null) return x;
- return copyOnModification(x, key, valueWithCheck.value, next);
- });
- };
- export const decomap = deepCopyOnMap;
- 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};
- };
|