[Utils] Fix findInTree (#32)
This commit is contained in:
parent
2201ff3a1d
commit
c54f9fe426
2 changed files with 38 additions and 30 deletions
7
src/def.d.ts
vendored
7
src/def.d.ts
vendored
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 {
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
function treeSearch(tree: SearchTree, filter: SearchFilter, opts: Required<FindInTreeOptions>, depth: number): any {
|
||||||
|
if (depth > opts.maxDepth) return;
|
||||||
if (!tree) return;
|
if (!tree) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (filter(tree)) return tree;
|
||||||
|
} catch {}
|
||||||
|
|
||||||
if (Array.isArray(tree)) {
|
if (Array.isArray(tree)) {
|
||||||
for (const item of tree) {
|
for (const item of tree) {
|
||||||
const found = doSearch(item, filter, { walkable, ignore });
|
if (typeof item !== "object" || item === null) continue;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const found = treeSearch(item, filter, opts, depth + 1);
|
||||||
if (found) return found;
|
if (found) return found;
|
||||||
|
} catch {}
|
||||||
}
|
}
|
||||||
} else if (typeof tree === "object") {
|
} else if (typeof tree === "object") {
|
||||||
for (const key of Object.keys(tree)) {
|
for (const key of Object.keys(tree)) {
|
||||||
if (walkable != null && walkable.includes(key)) continue;
|
if (typeof tree[key] !== "object" || tree[key] === null) continue;
|
||||||
|
if (opts.walkable.length && !opts.walkable.includes(key)) continue;
|
||||||
if (ignore.includes(key)) continue;
|
if (opts.ignore.includes(key)) continue;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const found = doSearch(tree[key], filter, { walkable, ignore });
|
const found = treeSearch(tree[key], filter, opts, depth + 1);
|
||||||
if (found) return found;
|
if (found) return found;
|
||||||
} catch {}
|
} 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);
|
||||||
|
|
Loading…
Reference in a new issue