mirror of
https://github.com/serverless/serverless.git
synced 2025-12-08 19:46:03 +00:00
45 lines
1.3 KiB
JavaScript
45 lines
1.3 KiB
JavaScript
'use strict';
|
|
|
|
const _ = require('lodash');
|
|
|
|
/**
|
|
* Find all objects with a given value within a given root object.
|
|
* The search is implemented non-recursive to prevent stackoverflows and will
|
|
* do a complete deep search including arrays.
|
|
* @param root {Object} Root object for search
|
|
* @param value {Object} Value to search
|
|
* @returns {Array<String>} Paths to all self references found within the object
|
|
*/
|
|
function findReferences(root, value) {
|
|
const visitedObjects = [];
|
|
const resourcePaths = [];
|
|
const stack = [{ propValue: root, path: '' }];
|
|
|
|
while (!_.isEmpty(stack)) {
|
|
const property = stack.pop();
|
|
|
|
_.forOwn(property.propValue, (propValue, key) => {
|
|
let propKey;
|
|
if (_.isArray(property.propValue)) {
|
|
propKey = `[${key}]`;
|
|
} else {
|
|
propKey = _.isEmpty(property.path) ? `${key}` : `.${key}`;
|
|
}
|
|
if (propValue === value) {
|
|
resourcePaths.push(`${property.path}${propKey}`);
|
|
} else if (_.isObject(propValue)) {
|
|
// Prevent circular references
|
|
if (_.includes(visitedObjects, propValue)) {
|
|
return;
|
|
}
|
|
visitedObjects.push(propValue);
|
|
stack.push({ propValue, path: `${property.path}${propKey}` });
|
|
}
|
|
});
|
|
}
|
|
|
|
return resourcePaths;
|
|
}
|
|
|
|
module.exports = findReferences;
|