"use strict"; const isIterable = require("is-iterable"); const mapAsync = require("../map-async"); module.exports = async function treeMapAsync(tree, mapper, options = {}) { let key = options.key ?? "children"; async function step(subtree) { let mapped = await mapper(subtree); let modifiedProperties = {}; if (isIterable(mapped[key])) { modifiedProperties[key] = await mapAsync(mapped[key], step); } else if (mapped[key] != null && typeof mapped[key] === "object") { modifiedProperties[key] = await step(mapped[key]); } // We track modified properties separately and (immutably) merge them at the end, because it's the fastest way to ensure that we don't mutate the input object under any circumstances return { ... mapped, ... modifiedProperties }; } return isIterable(tree) ? mapAsync(tree, step) : step(tree); };