GoonCord/src/lib/utils/findInTree.ts

52 lines
1.7 KiB
TypeScript
Raw Normal View History

2023-03-08 01:39:11 +01:00
// This has been completely reimplemented at this point, but the disclaimer at the end of disclaimers still counts.
2023-01-14 02:39:10 +00:00
// https://github.com/Cordwood/Cordwood/blob/91c0b971bbf05e112927df75415df99fa105e1e7/src/lib/utils/findInTree.ts
2022-10-18 23:21:58 +01:00
2024-02-23 15:11:35 +08:00
export type SearchTree = Record<string, any>;
export type SearchFilter = (tree: SearchTree) => boolean;
export interface FindInTreeOptions {
walkable?: string[];
ignore?: string[];
maxDepth?: number;
}
2022-10-18 23:21:58 +01:00
2023-03-08 01:39:11 +01:00
function treeSearch(tree: SearchTree, filter: SearchFilter, opts: Required<FindInTreeOptions>, depth: number): any {
if (depth > opts.maxDepth) return;
if (!tree) return;
2022-10-18 23:21:58 +01:00
2023-03-08 01:39:11 +01:00
try {
if (filter(tree)) return tree;
} catch {}
2022-10-18 23:21:58 +01:00
2023-03-08 01:39:11 +01:00
if (Array.isArray(tree)) {
for (const item of tree) {
if (typeof item !== "object" || item === null) continue;
2022-10-18 23:21:58 +01:00
2023-03-08 01:39:11 +01:00
try {
const found = treeSearch(item, filter, opts, depth + 1);
2022-10-18 23:21:58 +01:00
if (found) return found;
2023-03-08 01:39:11 +01:00
} catch {}
}
} else if (typeof tree === "object") {
for (const key of Object.keys(tree)) {
if (typeof tree[key] !== "object" || tree[key] === null) continue;
if (opts.walkable.length && !opts.walkable.includes(key)) continue;
if (opts.ignore.includes(key)) continue;
try {
const found = treeSearch(tree[key], filter, opts, depth + 1);
if (found) return found;
} catch {}
2022-10-18 23:21:58 +01:00
}
}
2023-03-08 01:39:11 +01:00
}
export const findInTree = (
2023-03-08 01:39:11 +01:00
tree: SearchTree,
filter: SearchFilter,
{
walkable = [],
ignore = [],
maxDepth = 100
}: FindInTreeOptions = {},
): any | undefined => treeSearch(tree, filter, { walkable, ignore, maxDepth }, 0);