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

"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;
};