You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
44 lines
1.1 KiB
JavaScript
44 lines
1.1 KiB
JavaScript
"use strict";
|
|
|
|
const isIterable = require("is-iterable");
|
|
const firstValue = require("../first-value");
|
|
|
|
const { validateArguments } = require("@validatem/core");
|
|
const required = require("@validatem/required");
|
|
const isFunction = require("@validatem/is-function");
|
|
const isString = require("@validatem/is-string");
|
|
const defaultTo = require("@validatem/default-to");
|
|
|
|
module.exports = function findInTree(_tree, _predicate, _options) {
|
|
let [ tree, predicate, { key } ] = validateArguments(arguments, {
|
|
tree: [ required ], // TODO: Make stricter?
|
|
predicate: [ required, isFunction ],
|
|
options: [ defaultTo({}), {
|
|
key: [ defaultTo("children", isString) ]
|
|
}]
|
|
});
|
|
|
|
function step(subtree) {
|
|
if (predicate(subtree)) {
|
|
return subtree;
|
|
} else {
|
|
let nextChild = subtree[key];
|
|
|
|
if (isIterable(nextChild)) {
|
|
return firstValue(nextChild, step);
|
|
} else if (nextChild != null && typeof nextChild === "object") {
|
|
return step(nextChild);
|
|
} else {
|
|
// TODO: Should an explicit sentinel value be used for this?
|
|
return undefined;
|
|
}
|
|
}
|
|
}
|
|
|
|
let finalResult = isIterable(tree)
|
|
? firstValue(tree, step)
|
|
: step(tree);
|
|
|
|
return finalResult;
|
|
};
|