set.js

import {
	nodePathToKeys,
	nodePathToKeysChildren
} from './utils';

/**
 * @module set
 */

/**
 * Once fully applied, this returns a new tree containing the new node `value` at the location determined by `nodePath`.
 * If an equivalent node already exists in this tree it will be replaced.
 * If any keys on `nodePath` do not exist, a new Immutable `Map` will be created at the missing key.
 *
 * Be aware that by setting values on deep nodes that don't yet exist,
 * this may cause `Maps` to be created for child `Iterables` where other types of `Iterables` may be used for children elsewhere in the tree.
 * This will be addressed in a future release.
 *
 * When no `childPath` is provided then this is functionally equivalent to Immutable's `setIn()` method.
 *
 * @param {NodePath} nodePath A NodePath used to uniquely identify the node to set.
 * @param {*} value The value to set the node to.
 * @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node.
 * @return {InputFunction} A partially applied function which accepts a single tree `Iterable`, and returns the modified tree `Iterable`.
 */

function deepSet(nodePath, value, childPath=null) {
  return (tree) => tree.setIn(nodePathToKeys(nodePath, childPath), value);
}

/**
 * Once fully applied, this returns a new tree where the children `Iterable` of the node at `nodePath` are set to `value`.
 * If no node exists at `nodePath` then an Immutable `Map` will be created at that location.
 *
 * This is intended to be used with a `childPath`, but if no `childPath` is provided
 * then this is functionally equivalent to both Immutable's `setIn()` method and `deepSet()`.
 *
 * @param {NodePath} nodePath A `NodePath` used to uniquely identify a node whose children will be set.
 * @param {*} value The value to set the node to.
 * @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node.
 * @return {InputFunction} A partially applied function which accepts a single tree `Iterable`, and returns the modified tree `Iterable`.
 */

function deepSetChildren(nodePath, value, childPath=null) {
  return (tree) => tree.setIn(nodePathToKeysChildren(nodePath, childPath), value);
}

export {
  deepSet,
  deepSetChildren
}