index.js


/**
 * 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';