[Utils] Fix findInTree (#32)

This commit is contained in:
redstonekasi 2023-03-08 01:39:11 +01:00 committed by GitHub
parent 2201ff3a1d
commit c54f9fe426
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 30 deletions

7
src/def.d.ts vendored
View file

@ -35,7 +35,8 @@ interface Logger {
verbose: LoggerFunction; verbose: LoggerFunction;
} }
type SearchFilter = (tree: any) => boolean; type SearchTree = Record<string, any>;
type SearchFilter = (tree: SearchTree) => boolean;
interface FindInTreeOptions { interface FindInTreeOptions {
walkable?: string[]; walkable?: string[];
ignore?: string[]; ignore?: string[];
@ -349,8 +350,8 @@ interface VendettaObject {
}; };
utils: { utils: {
copyText: (content: string) => void; copyText: (content: string) => void;
findInReactTree: (tree: { [key: string]: any }, filter: SearchFilter) => any; findInReactTree: (tree: SearchTree, filter: SearchFilter) => any;
findInTree: (tree: { [key: string]: any }, filter: SearchFilter, options: FindInTreeOptions) => any; findInTree: (tree: SearchTree, filter: SearchFilter, options: FindInTreeOptions) => any;
safeFetch: (input: RequestInfo, options: RequestInit) => Promise<Response>; safeFetch: (input: RequestInfo, options: RequestInit) => Promise<Response>;
unfreeze: (obj: object) => object; unfreeze: (obj: object) => object;
}; };

View file

@ -1,38 +1,45 @@
// This has been completely reimplemented at this point, but the disclaimer at the end of disclaimers still counts.
// https://github.com/Cordwood/Cordwood/blob/91c0b971bbf05e112927df75415df99fa105e1e7/src/lib/utils/findInTree.ts // https://github.com/Cordwood/Cordwood/blob/91c0b971bbf05e112927df75415df99fa105e1e7/src/lib/utils/findInTree.ts
import { FindInTreeOptions, SearchFilter } from "@types"; import { FindInTreeOptions, SearchTree, SearchFilter } from "@types";
export default function findInTree(tree: { [key: string]: any }, filter: SearchFilter, { walkable = [], ignore = [], maxDepth = 100 }: FindInTreeOptions = {}): any { function treeSearch(tree: SearchTree, filter: SearchFilter, opts: Required<FindInTreeOptions>, depth: number): any {
let iteration = 0; if (depth > opts.maxDepth) return;
if (!tree) return;
function doSearch(tree: { [key: string]: any }, filter: SearchFilter, { walkable = [], ignore = [] }: FindInTreeOptions = {}): any { try {
iteration += 1; if (filter(tree)) return tree;
if (iteration > maxDepth) return; } catch {}
if (typeof filter === "string") { if (Array.isArray(tree)) {
if (tree.hasOwnProperty(filter)) return tree[filter]; for (const item of tree) {
} else if (filter(tree)) return tree; if (typeof item !== "object" || item === null) continue;
if (!tree) return; try {
const found = treeSearch(item, filter, opts, depth + 1);
if (Array.isArray(tree)) {
for (const item of tree) {
const found = doSearch(item, filter, { walkable, ignore });
if (found) return found; if (found) return found;
} } catch {}
} else if (typeof tree === "object") { }
for (const key of Object.keys(tree)) { } else if (typeof tree === "object") {
if (walkable != null && walkable.includes(key)) continue; 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;
if (ignore.includes(key)) continue; try {
const found = treeSearch(tree[key], filter, opts, depth + 1);
try { if (found) return found;
const found = doSearch(tree[key], filter, { walkable, ignore }); } catch {}
if (found) return found;
} catch {}
}
} }
} }
return doSearch(tree, filter, { walkable, ignore });
} }
export default (
tree: SearchTree,
filter: SearchFilter,
{
walkable = [],
ignore = [],
maxDepth = 100
}: FindInTreeOptions = {},
): any | undefined => treeSearch(tree, filter, { walkable, ignore, maxDepth }, 0);