UNPKG

theprogrammablemind_4wp

Version:

105 lines (95 loc) 3.29 kB
function areFirstNEqual(arr1, arr2, n) { if (n <= 0) return true; if (arr1.length < n || arr2.length < n) return false; for (let i = 0; i < n; i++) { if (arr1[i] !== arr2[i]) { return false; } } return true; } function project(source, filters, path=[]) { if (['string', 'number'].includes(typeof source)) { return source } if (Array.isArray(source)) { const result = [] for (const value of source) { result.push(project(value, filters, [...path, '*'])) } return result } function isPlainObject(obj) { return Object.prototype.toString.call(obj) === '[object Object]'; } if (!isPlainObject(source) && !Array.isArray(source)) { return source } if (Object.keys(source).length === 0 && filters.length === 0) { return {}; } // Find the applicable filter for the current context const filter = filters.find(f => f.match({ context: source })); if (!filter) { if (Array.isArray(source)) { return source.map((element) => project(element, filters, [...path, '*'])) } return {}; } // Get the properties to include from the apply function let properties = filter.apply(source); // update const updatedProperties = [] for (const property of properties) { // property that contains a list of properties to be checked if (property.properties) { for (const moreProperty of source[property.properties] || []) { updatedProperties.push(moreProperty) } } else { updatedProperties.push(property) } } properties = updatedProperties // Build the result object const result = {}; properties.forEach(prop => { if (prop.path && (prop.path.length === path.length + 1) && areFirstNEqual(path, prop.path, path.length) && source.hasOwnProperty(prop.path[path.length])) { const endProp = prop.path[path.length] if (Array.isArray(source[endProp])) { result[endProp] = [] for (const key in source[endProp]) { result[endProp].push(project(source[endProp][key], filters, [...path, endProp, key])) } } else { result[endProp] = {} for (const key in source[endProp]) { result[endProp][key] = project(source[endProp][key], filters, [...path, endProp, key]) } } } else if (source.hasOwnProperty(prop)) { // If the property is an object and not null, recursively project it if (typeof source[prop] === 'object' && source[prop] !== null) { result[prop] = project(source[prop], filters, [...path, prop]); } else { // Copy primitive or null properties directly result[prop] = source[prop]; } } else if (prop.property && source.hasOwnProperty(prop.property)) { // If the property is an object and not null, recursively project it if (typeof source[prop.property] === 'object' && source[prop.property] !== null) { result[prop.property] = {} for (const key of prop.check) { result[prop.property][key] = project(source[prop.property][key], filters, [...path, prop.property, key]); } } else { // Copy primitive or null properties directly result[prop] = source[prop]; } } }); return result; } module.exports = { project }