2022-10-18 23:21:58 +01:00
|
|
|
/*
|
2022-10-22 15:12:38 +01:00
|
|
|
Disclaimer: https://github.com/Cordwood/Cordwood/blob/91c0b971bbf05e112927df75415df99fa105e1e7/src/lib/utils/findInTree.ts
|
|
|
|
|
*/
|
2022-10-18 23:21:58 +01:00
|
|
|
|
|
|
|
|
import { FindInTreeOptions, SearchFilter } from "@types";
|
|
|
|
|
|
|
|
|
|
export default function findInTree(tree: { [key: string]: any }, filter: SearchFilter, { walkable = [], ignore = [], maxDepth = 100 }: FindInTreeOptions = {}): any {
|
|
|
|
|
let iteration = 0;
|
|
|
|
|
|
|
|
|
|
function doSearch(tree: { [key: string]: any }, filter: SearchFilter, { walkable = [], ignore = [] }: FindInTreeOptions = {}): any {
|
|
|
|
|
iteration += 1;
|
|
|
|
|
if (iteration > maxDepth) return;
|
|
|
|
|
|
|
|
|
|
if (typeof filter === "string") {
|
|
|
|
|
if (tree.hasOwnProperty(filter)) return tree[filter];
|
|
|
|
|
} else if (filter(tree)) return tree;
|
|
|
|
|
|
|
|
|
|
if (!tree) return;
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(tree)) {
|
|
|
|
|
for (const item of tree) {
|
|
|
|
|
const found = doSearch(item, filter, { walkable, ignore });
|
|
|
|
|
if (found) return found;
|
|
|
|
|
}
|
|
|
|
|
} else if (typeof tree === "object") {
|
|
|
|
|
for (const key of Object.keys(tree)) {
|
|
|
|
|
if (walkable != null && walkable.includes(key)) continue;
|
|
|
|
|
|
|
|
|
|
if (ignore.includes(key)) continue;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const found = doSearch(tree[key], filter, { walkable, ignore });
|
|
|
|
|
if (found) return found;
|
|
|
|
|
} catch {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return doSearch(tree, filter, { walkable, ignore });
|
|
|
|
|
}
|