UNPKG

@onesy/utils

Version:
97 lines (85 loc) 3.19 kB
import is from './is'; import flattenObject from './flattenObject'; import unflattenObject from './unflattenObject'; const getObjectProperties = function (object, path) { let unflatten = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; const values = []; // object or array if (!((is('array', object) || is('object', object)) && is('string', path) && !!path.length)) return values; const separator = '.'; // Flatten the object const flattened = flattenObject(object, true); const paths = Object.keys(flattened); let pathsToUse = paths.map(item => ({ path: item, value: undefined, usable: item, used: '' })); const parts = path.split(separator).filter(Boolean); if (!parts.length) return values; parts.forEach((part, index) => { // ** // find all paths to use whose // usable path includes the first next part const partNext = parts[index + 1]; const indexLast = parts.length - 1 === index; if (part === '**') { pathsToUse = pathsToUse.filter(item => { // If no part next // ie. a.** // all are usable if (!partNext) return item; let itemParts = item.usable.split(separator).filter(Boolean); const index_ = itemParts.findIndex(itemPart => itemPart === partNext); const use = index_ > -1; // update // usable path if (use) { itemParts = itemParts.slice(index_); item.usable = itemParts.join(separator); item.used += "".concat(!item.used ? '' : '.').concat(part); return item; } return false; }); } // * // use all the properties // ignore their first usable property // ie. object property or index else if (part === '*') { pathsToUse = pathsToUse.filter(item => { const itemNew = item; const itemParts = itemNew.usable.split(separator).filter(Boolean); // only use // exact path items if (indexLast) return itemParts.length === 1; // remove the first prop // object property or index itemParts.shift(); itemNew.usable = itemParts.join(separator); item.used += "".concat(!item.used ? '' : '.').concat(part); return true; }); } // regular // whose first usable item is // equal to part else { pathsToUse = pathsToUse.filter(item => { if (!item.usable.length) return false; const itemParts = item.usable.split(separator).filter(Boolean); const use = itemParts[0] === part; // update // usable path if (use) { itemParts.shift(); item.usable = itemParts.join(separator); item.used += "".concat(!item.used ? '' : '.').concat(part); } // if last index // only return items // whose usable path // matches exactly if (indexLast) return !item.usable.length; return use; }); } }); const value = {}; pathsToUse.forEach(item => value[item.path] = item.value !== undefined ? item.value : flattened[item.path]); return !unflatten ? value : unflattenObject(value); }; export default getObjectProperties;