all files / src/ initializeState.js

97.92% Statements 47/48
92.86% Branches 52/56
100% Functions 8/8
97.06% Lines 33/34
6 statements, 1 function, 3 branches Ignored     
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62   104×                 57× 57×   56×   55× 135× 135× 15×   120× 120× 120× 120×   114×   17×     17× 17× 17× 17× 17× 16×   15×               97×   120×   99×        
import {makeFieldValue} from './fieldValue';
 
const makeEntry = (value, previousValue, overwriteValues) => {
  return makeFieldValue(value === undefined ? {} : {
    initial: value,
    value: overwriteValues ? value : previousValue
  });
};
 
/**
 * Sets the initial values into the state and returns a new copy of the state
 */
const initializeState = (values, fields, state = {}, overwriteValues = true) => {
  if (!fields) {
    throw new Error('fields must be passed when initializing state');
  }
  if (!values || !fields.length) {
    return state;
  }
  const initializeField = (path, src, dest) => {
    const dotIndex = path.indexOf('.');
    if (dotIndex === 0) {
      return initializeField(path.substring(1), src, dest);
    }
    const openIndex = path.indexOf('[');
    const closeIndex = path.indexOf(']');
    const result = { ...dest } || {};
    if (dotIndex >= 0 && (openIndex < 0 || dotIndex < openIndex)) {
      // is dot notation
      const key = path.substring(0, dotIndex);
      result[ key ] = src[ key ] && initializeField(path.substring(dotIndex + 1), src[ key ], result[ key ] || {});
    } else if (openIndex >= 0 && (dotIndex < 0 || openIndex < dotIndex)) {
      // is array notation
      Iif (closeIndex < 0) {
        throw new Error(`found '[' but no ']': '${path}'`);
      }
      const key = path.substring(0, openIndex);
      const srcArray = src[ key ];
      const destArray = result[ key ];
      const rest = path.substring(closeIndex + 1);
      if (Array.isArray(srcArray)) {
        if (rest.length) {
          // need to keep recursing
          result[ key ] = srcArray.map((srcValue, srcIndex) =>
            initializeField(rest, srcValue, destArray && destArray[ srcIndex ]));
        } else {
          result[ key ] = srcArray.map((srcValue, srcIndex) =>
            makeEntry(srcValue, destArray && destArray[ srcIndex ] && destArray[ srcIndex ].value, overwriteValues));
        }
      } else {
        result[ key ] = [];
      }
    } else {
      result[ path ] = makeEntry(src && src[ path ], dest && dest[ path ] && dest[ path ].value, overwriteValues);
    }
    return result;
  };
  return fields.reduce((accumulator, field) => initializeField(field, values, accumulator), { ...state });
};
 
export default initializeState;