All files / latest/src/handlers/set setAll.js

100% Statements 66/66
100% Branches 16/16
100% Functions 3/3
100% Lines 66/66

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 63 64 65 66 671x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 101x 33x 33x 101x 101x 1x 1x 1x 1x 1x 88x 88x 88x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 33x 33x 33x 33x 33x 101x 101x 88x 88x 88x 88x 88x 88x 88x 88x 101x 5x 13x 13x 13x 13x 13x 5x 5x 3x 3x 33x 33x 1x 1x  
const unlink = require('../basic/unlink.js');
const pathTransformer = require('../../helpers/pathTransformer');
const getPathElements = require('../../helpers/pathElements/getMultiple');
const setElement = require('./src/setElement');
const getAllKeysFromArray = require('../../helpers/pathElements/getKeys/getAllKeysFromArray');
const getAllKeysFromObject = require('../../helpers/pathElements/getKeys/getAllKeysFromObject');
 
/**
 * Get key values of all elements that need to be set
 */
// eslint-disable-next-line complexity
const getElementValues = (element, obj, tempObject, priorPath, fatalError) => {
  if (Array.isArray(tempObject)) {
    return element.wildcard ? getAllKeysFromArray(tempObject, fatalError) : getPathElements(element, unlink(obj), tempObject, 'number', priorPath, fatalError);
  }
  return element.wildcard ? getAllKeysFromObject(tempObject, fatalError) : getPathElements(element, unlink(obj), tempObject, 'string', priorPath, fatalError);
};
 
/**
 * Get value from element in object
 */
const getElementValue = (element) => {
  const resultKeys = Object.keys(element);
  return element[resultKeys[0]];
};
 
/**
 * Sets single value on specified path
 * @param {object} obj - object
 * @param {any} path - string or array representation of path to set.
 * @param {any} val - value to be set at specified path.
 * @param {boolean} fatalError - true if fatal error is desired if logical check is not satisfied.
 * @returns {object} object with newly set path in case that multiple logical checks
 * satisfy the first element will be set.
 */
const setAll = (obj, path, val, fatalError) => {
  const arrayPath = pathTransformer(path);
  const priorPath = [];
  let tempObject = obj;
 
  arrayPath.every((element, index) => {
    const elementValues = getElementValues(element, obj, tempObject, priorPath, fatalError);
    if (elementValues.length === 1) {
      const elementValue = getElementValue(elementValues[0]);
      tempObject = setElement(
        elementValue, tempObject, arrayPath[index + 1], arrayPath.length - 1 === index, val,
      );
      // eslint-disable-next-line prefer-destructuring
      arrayPath[index] = elementValues[0];
      priorPath.push(elementValues[0]);
      return true;
    } if (elementValues.length > 1) {
      elementValues.forEach((elementValue) => {
        const newPath = [
          ...arrayPath.slice(0, index), elementValue, ...arrayPath.slice(index + 1),
        ];
        return setAll(obj, newPath, val, fatalError);
      });
      return false;
    }
    return false;
  });
  return obj;
};
 
module.exports = setAll;