theprogrammablemind_4wp
Version:
105 lines (95 loc) • 3.29 kB
JavaScript
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
}