/**
* When passed as a parameter, `NodePath` can be a `List` or an `Array` of keys used to uniquely identify a node.
* Almost always used in conjunction with a `ChildPath`.
* Also accepts null in place of an empty `Array` or `List`.
*
* Whenever `NodePath` is returned from a function in the immutable-recursive library,
* it will always be a `List`.
*
* @example
* const tree = fromJS({
* name: "root",
* children: [
* {
* name: "child 1",
* children: [
* {name: "grandchild 1"},
* {name: "grandchild 2"}
* ]
* }
* {name: "child 2"}
* ]
* });
* // The NodePath for "root" is [] (or null)
* // The NodePath for "child 1" is [0]
* // The NodePath for "grandchild 2" is [0,1]
*
* const nestedMaps = fromJS({
* a: {
* b: "B",
* c: "C",
* d: {
* e: "E"
* }
* },
* f: "F"
* });
* // The NodePath for "A" is ['a']
* // The NodePath for "B" is ['a','b']
* // The NodePath for "E" is ['a','d','e']
*
* @typedef {Array|List|null} NodePath
*/
/**
* An `Array` or `List` of keys indicating where to find each node's children from within each node.
* This works in the same way as the `keyPath` parameter in Immutable's `getIn()` method.
* It also accepts null in place of an empty `Array` or `List`.
*
* @example
* // this tree would have a ChildPath of ['children'], as each node's children can be found in the 'children' iterable
* const tree = fromJS({
* name: "root",
* children: [
* {
* name: "child 1",
* children: [
* {name: "grandchild 1"},
* {name: "grandchild 2"}
* ]
* },
* {
* name: "child 2",
* children: []
* },
* {name: "child 3"}
* ]
* });
*
* // nested maps and lists like these don't require a ChildPath, as each Iterable contains its own children
* const nestedMaps = fromJS({
* a: {
* b: "B",
* c: "C",
* d: {
* e: "E"
* }
* },
* f: "F"
* });
*
* const nestedLists = fromJS([
* ["A","B","C"],
* ["D",["E","F"]],
* "G"
* );
*
* @typedef {Array|List|null} ChildPath
*/
/**
* InputFunction is a partially applied function returned from all 'deep' functions in immutable-recursive.
* It accepts an iterable, the tree of data you wish to call your deep function on,
* and returns the result of the deep function you're calling.
*
* For example, one way to use `deepGet` is to call it, passing in any parameters required, then call the returned function, passing in your data tree.
*
* ```js
* const nestedMaps = fromJS({
* a: {
* b: "B",
* c: "C",
* d: {
* e: "E"
* }
* },
* f: "F"
* });
*
* return deepGet(['a','b'])(nestedMaps); // returns "B"
* ```
*
* This design of using a partially applied function allows immutable-recursive's functions to be chained easily with Immutable,
* by using them inside of an `update()` method. This is the preferred usage pattern as it retains chainability.
*
* ```js
* return fromJS(someData)
* .get('tree')
* .update(deepGet(['a','b'])) // using deepGet in a chain
* .set('done', true)
* .toJS();
* ```
*
* You can also define a function to perform a specific operation, and use it multiple times by passing in different tree data.
*
* ```js
* // make every node's name uppercase
* const uppercaseNames = deepMap((node) => {
* return node.update('name', (name) => name.toUpperCase());
* }, ['children']);
*
* const a = fromJS(aDataTree).update(uppercaseNames);
* const b = fromJS(aDifferentDataTree).update(uppercaseNames);
* ```
*
* @callback InputFunction
* @param {Iterable} tree The tree Iterable to be processed by one of the deep functions.
* @return {Iterable} The modified iterable.
*/
/**
* A function required as an argument for the `deepMap` functions.
*
* @callback Mapper
* @param {*} value The value to update.
* @param {List} nodePath The current node's `NodePath`, a `List` of keys used to uniquely identify the current node.
* @param {Iterable} tree The original `tree` passed into the map function.
* @return {*} The replacement value.
*/
/**
* A function required as an argument for the `deepUpdate` functions.
*
* @callback Updater
* @param {*} value The value to update.
* @return {*} The replacement value.
*/
/**
* A function required as an argument for the `deepFilter` functions.
*
* @callback Filterer
* @param {*} value The value to filter.
* @param {List} nodePath The current node's `NodePath`, a `List` of keys used to uniquely identify the current node.
* @param {Iterable} tree The original `tree` passed into the map function.
* @return {*} The replacement value.
*/
/**
* A function required as an argument for the `deepReduce` functions.
*
* @callback Reducer
* @param {*} reduction The current reduction.
* @param {*} value The current value.
* @param {List} nodePath The current node's `NodePath`, a `List` of keys used to uniquely identify the current node.
* @param {Iterable} tree The original `tree` passed into the map function.
* @return {*} The new reduced value.
*/
export {
deepGet,
deepGetChildren
} from './get';
export {
deepUpdate,
deepUpdateChildren
} from './update';
export {
deepSet,
deepSetChildren
} from './set';
export {
deepDelete,
deepDeleteChildren
} from './delete';
export {
deepMap,
deepMapLeaves,
deepMapParents,
deepMapOutwards,
deepMapLeavesOutwards,
deepMapParentsOutwards
} from './map';
export {
deepReduce,
deepReduceLeaves,
deepReduceParents,
deepReduceOutwards,
deepReduceLeavesOutwards,
deepReduceParentsOutwards
} from './reduce';
export {
deepFilter
} from './filter';
export {
deepPick
} from './pick';
import {
asList,
blankNode,
keysToPath,
keysToPathChildren,
isLeaf,
pick
} from './utils';