UNPKG

immutable-setter

Version:

'Deep properties setter and getter for immutable objects'

182 lines (143 loc) 4.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; exports.setIn = setIn; exports.deleteIn = deleteIn; exports.getIn = getIn; require('object-assign-shim'); function formatKeyPath(keyPath) { return JSON.toString(keyPath); } function isValidObject(obj) { return (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && obj !== null; } function formatInvalidObjectAtPath(keyPath) { return 'Invalid value found at path ' + formatKeyPath(keyPath) + '. Object was expected'; } function validateKey(key, isArray) { if (isArray) { if (typeof key !== 'number') { return 'Unexpected key type in the keyPath: ' + key + ' expected to be index of the array'; } } else { if (!key && key !== 0) { return 'Key value was not set'; } } } function copyObject(obj, isArray) { return isArray ? obj.slice() : Object.assign({}, obj); } function setIn(obj, keyPath, val) { function setValue(obj, key, isArray, val) { if (obj[key] === val) { return obj; } var copy = copyObject(obj, isArray); copy[key] = val; return copy; } function setChild(obj, keyPath, keyIndex, val) { var key = keyPath[keyIndex]; var isArray = void 0; if (typeof obj === 'undefined' || obj === null) { var typeOfKey = typeof key === 'undefined' ? 'undefined' : _typeof(key); if (key === null || typeOfKey === 'number' || typeOfKey === 'undefined') { obj = []; } else { obj = {}; } } //to check if we encounter basic value instead of object or array if (!isValidObject(obj)) { throw formatInvalidObjectAtPath(keyPath.slice(0, keyIndex - 1)); } isArray = Array.isArray(obj); if (isArray && (typeof key === 'undefined' || key === null)) { key = obj.length; } var error = validateKey(key, isArray); if (error) { throw 'Invalid keyPath ' + formatKeyPath(keyPath) + ': ' + error; } if (keyIndex === keyPath.length - 1) { return setValue(obj, key, isArray, val); } else { //recursion var newChild = setChild(obj[key], keyPath, keyIndex + 1, val); return setValue(obj, key, isArray, newChild); } } return setChild(obj, keyPath, 0, val); } function deleteIn(obj, keyPath) { function isKeyFound(obj, key, isArray) { if (isArray) { return key >= 0 && key < obj.length; } else { return obj.hasOwnProperty(key); } } function deleteKeyFromObject(obj, key, isArray) { var copy = copyObject(obj, isArray); if (isArray) { copy.splice(key, 1); } else { delete copy[key]; } return copy; } function deleteChild(obj, keyPath, keyIndex) { if (!isValidObject(obj)) { throw formatInvalidObjectAtPath(keyPath.slice(0, keyIndex - 1)); } var isArray = Array.isArray(obj); var key = keyPath[keyIndex]; var error = validateKey(key, isArray); if (error) { throw 'Invalid keyPath ' + formatKeyPath(keyPath) + ': ' + error; } if (!isKeyFound(obj, key, isArray)) { return obj; } else if (keyIndex === keyPath.length - 1) { //key to actual value to be removed return deleteKeyFromObject(obj, key, isArray); } else { var child = obj[key]; //recursion var newChild = deleteChild(child, keyPath, keyIndex + 1); if (child === newChild) { return obj; } else { var copy = copyObject(obj, isArray); copy[key] = newChild; return copy; } } } return deleteChild(obj, keyPath, 0); } function getIn(obj, keyPath) { function readValue(obj, keyArr, keyIndex) { if (!obj) { return undefined; } if (!isValidObject(obj)) { throw formatInvalidObjectAtPath(keyPath.slice(0, keyIndex - 1)); } var key = keyArr[keyIndex]; var val = obj[key]; if (keyIndex >= keyArr.length - 1) { return val; } else { return readValue(val, keyArr, keyIndex + 1); } } if (keyPath.length === 0) { return obj; } else { return readValue(obj, keyPath, 0); } }