UNPKG

immutable-path

Version:

Immutable `get`, `set`, `has`, `unset` deep path operations libraray for object, array and `Map`.

109 lines 5.07 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const get_1 = __importDefault(require("./util/get")); const set_1 = __importDefault(require("./util/set")); const unset_1 = __importDefault(require("./util/unset")); const has_1 = __importDefault(require("./util/has")); const helper_1 = require("./util/helper"); /** * Sets the property value of path on object/array/Map immutably without changing input. If a portion of path does not exist it's created. * Provided `atomicClasses` is used to determine which type of objects are treated as atomic. Atomic classes are * treated like primitives pretending they don't have attributes. See example below. If `preferMap` is true, * when new objects are needed, they are created as `Map` instead of object. * * @param source is the object/array/map to set. * @param path is the path of the property to set. * @param value is the value to set. * @param __namedParameters are options. * @returns new object/array/Map. * @example * const a = set({ x: new Date() }, "x.y", 3); // 3 is not assigned to atomic class Date. Insted it is replaced: { x: { y: 3 } } * const b = set({ x: { z: 1 } }, "x.y", 3); // 3 is not assigned to `x.y`: { x: { y: 3, z: 1 } } * const c = set({ }, "x.y", 3); // 3 is not assigned to `x.y`: { x: { y: 3 } } * const c = set({ }, "x.y", 3, { preferMap: true }); // Map([[x, new Map([[y, 3]])]]); */ function set(source, path, value, { /** Atomic classes are treated like a scalar, because MOST PROBABLY user did not intend to update a property of it. Instead they want to replace it. */ atomicClasses = helper_1.defaultAtomicClasses, /** If an attribute for a non-existing object should be created, whether to create a `Map` instead of `object`. */ preferMap = false, } = {}, root = source) { const options = { atomicClasses, preferMap }; const [key, ...remainingPath] = helper_1.getPath(path); const oldValueOfKey = helper_1.getAddressableValue(source, key, options, remainingPath[0]); const newValueOfKey = remainingPath.length > 0 ? set(oldValueOfKey, remainingPath, value, options, root) : value; return set_1.default(source, key, newValueOfKey, root); } exports.set = set; /** * Removes the property at path of object and returns it. Does not change input value. * * @param source is the object/array/map to unset a value. * @param path is the path of the property to unset. * @param __namedParameters are options. * @returns new object/array/Map. */ function unset(source, path, { /** Atomic classes are treated like a scalar, because MOST PROBABLY user did not intend to update a property of it. Instead they want to replace it. */ atomicClasses = helper_1.defaultAtomicClasses, /** After unsetting a key/index if object/array/Map becomes empty, it is also unset in parent. */ unsetEmpty = true, /** If an attribute for a non-existing object should be created, whether to create a `Map` instead of `object`. */ preferMap = false, } = {}) { const options = { atomicClasses, unsetEmpty, preferMap }; const [key, ...remainingPath] = helper_1.getPath(path); const addressableValue = helper_1.getAddressableValue(source, key, options); if (remainingPath.length > 0) { if (addressableValue) { const unsetValue = unset(addressableValue, remainingPath, options); const unsetFurther = unsetEmpty && helper_1.isEmpty(unsetValue, atomicClasses); if (!unsetFurther) return set_1.default(source, key, unsetValue); } else { return source; } } return unset_1.default(source, key); } exports.unset = unset; /** * Gets the property value at path of object/array/Map. If the resolved value is undefined the defaultValue is used in its place. * * @param source is the object/array/map to query. * @param path is the path of the property to get. * @param defaultValue is the value returned if the resolved value is `undefined`. * @returns the resolved value. */ function get(source, path, defaultValue) { let result = source; // eslint-disable-next-line no-restricted-syntax for (const key of helper_1.getPath(path)) { result = get_1.default(result, key); if (result === undefined) return defaultValue; } return result; } exports.get = get; /** * Checks if path is a direct property of object/array/Map. * * @param source is the object/array/Map to query. * @param path is the path to check. * @returns whether path is a direct property of object/array/Map. */ function has(source, path) { let current = source; // eslint-disable-next-line no-restricted-syntax for (const key of helper_1.getPath(path)) { if (!has_1.default(current, key)) return false; current = get_1.default(current, key); } return true; } exports.has = has; //# sourceMappingURL=immutable-object-path.js.map