All files / latest/src/handlers/get get.js

100% Statements 98/98
100% Branches 24/24
100% Functions 5/5
100% Lines 98/98

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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 991x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 7x 7x 7x 6x 7x 1x 1x 7x 5x 5x 5x 2x 2x 5x 5x 1x 1x 1x 1x 1x 129x 5x 5x 124x 124x 1x 1x 1x 1x 1x 37x 37x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 354x 354x 22x 22x 332x 354x 290x 290x 38x 38x 38x 129x 54x 54x 54x 54x 121x 75x 75x 75x 75x 75x 128x 128x 128x 128x 128x 128x 38x 38x 38x 1x 1x  
const JsonGo = require('../../../index');
const pathTransformer = require('../../helpers/pathTransformer');
const stringify = require('../basic/stringify');
const getSinglePathElement = require('../../helpers/pathElements/getSingle');
const doesPathIndicateComplexity = require('./src/doesPathIndicateComplexity');
const simpleGet = require('./src/simpleGet');
const validateOutput = require('./src/validateOutput');
const getAllKeysFromObject = require('../../helpers/pathElements/getKeys/getAllKeysFromObject');
const getAllKeysFromArray = require('../../helpers/pathElements/getKeys/getAllKeysFromArray');
 
const getCache = {};
 
/**
 * Handle wildcard, checks for each key whether remaining path is found and returns first key that matches
 */
const getFirstKey = (tempObject, arrayPath, getType, index, obj, priorPath) => {
  const keys = getType === 'number' ? getAllKeysFromArray(tempObject) : getAllKeysFromObject(tempObject);
  let result;
  keys.some((key) => {
    let iterationResult;
    const remainingPath = arrayPath.slice(index + 1);
    if (doesPathIndicateComplexity(remainingPath)) {
      iterationResult = new JsonGo.Json(obj).get([...priorPath, key, ...remainingPath]);
    } else {
      iterationResult = simpleGet(tempObject, [key, ...remainingPath]);
    }
    if (iterationResult !== undefined) {
      result = key[getType];
      return true;
    }
    return false;
  });
  return result;
};
 
/**
 * Get name of element either from wildcard or from other type of element
 */
const getPathElement = (element, obj, tempObject, getType, priorPath, arrayPath, index) => {
  if (element.wildcard) {
    return getFirstKey(tempObject, arrayPath, getType, index, obj, priorPath);
  }
  return getSinglePathElement(element, obj, tempObject, getType, priorPath);
};
 
/**
 * Store result into cache so that it can be reused
 */
const setCache = (stringifiedPath, obj, tempObject) => {
  getCache[stringifiedPath] = { object: obj, result: tempObject };
};
 
/**
 * Validate if cache is for the right object
 */
const validateCache = (cache, obj) => cache && cache.object === obj;
 
/**
 * Retreives single value from objects specified path
 * @param {Object} obj - object/array from which value should be retreived.
 * @param {any} path - string or array representation of path to set.
 * @returns {any} returns value found at specified path, in case that multiple logical checks
 * satisfy the first element will be returned
 */
const get = (obj, path) => {
  const stringifiedPath = stringify(path);
  if (validateCache(getCache[stringifiedPath], obj)) {
    return getCache[stringifiedPath].result;
  }
  const arrayPath = pathTransformer(path);
  if (!doesPathIndicateComplexity(arrayPath)) {
    return simpleGet(obj, arrayPath);
  }
  const priorPath = [];
  let tempObject = obj;
  arrayPath.every((element, index) => {
    if (Array.isArray(tempObject)) {
      const elementValue = getPathElement(element, obj, tempObject, 'number', priorPath, arrayPath, index);
      tempObject = tempObject[elementValue];
      arrayPath[index] = elementValue;
      priorPath.push({ number: elementValue });
    } else {
      const elementValue = getPathElement(element, obj, tempObject, 'string', priorPath, arrayPath, index);
      tempObject = tempObject[elementValue];
      arrayPath[index] = elementValue;
      priorPath.push({ string: elementValue });
    }
    const {
      shouldItContinue, newTempObject,
    } = validateOutput(tempObject, arrayPath.length - 1 === index);
    tempObject = newTempObject;
    return shouldItContinue;
  });
  setCache(stringifiedPath, obj, tempObject);
  return tempObject;
};
 
module.exports = get;