Socket
Socket
Sign inDemoInstall

simple-update-in

Package Overview
Dependencies
Maintainers
1
Versions
66
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

simple-update-in - npm Package Compare versions

Comparing version 1.1.2-master.cf20461 to 1.2.0

11

CHANGELOG.md

@@ -9,4 +9,13 @@ # Changelog

## [1.1.1]
## [1.2.0] - 2018-04-14
### Added
- If after `updater` result in nothing change (triple-equal `===`), will return untouched
- `updater` returned `undefined` will be treated as removing the item
### Fixed
- Append not creating sub-structure correctly
- `updateIn([1, 2], [-1, 0], 'Hello')` should return `[1, 2, ['Hello']]` instead of `[1, 2, 'Hello']`
## [1.1.1] - 2018-04-06
### Fixed
- Move `babel` and `gulp` into `devDependencies`

@@ -13,0 +22,0 @@

68

lib/index.js

@@ -13,7 +13,11 @@ 'use strict';

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function setIn(obj, path, updater) {
if (!Array.isArray(path)) {
throw new Error('path must be an array');
}
if (!path.length) {

@@ -27,34 +31,58 @@ return updater(obj);

var value = typeof obj !== 'undefined' && obj[accessor];
var nextObj = obj;
if (typeof accessor === 'string' && ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object' || Array.isArray(obj))) {
obj = {};
} else if (typeof accessor === 'number' && !Array.isArray(obj)) {
obj = [];
if (typeof accessor === 'string' && ((typeof nextObj === 'undefined' ? 'undefined' : _typeof(nextObj)) !== 'object' || Array.isArray(nextObj))) {
nextObj = {};
} else if (typeof accessor === 'number' && !Array.isArray(nextObj)) {
nextObj = [];
}
if (typeof accessor === 'number') {
obj = obj && obj.slice();
if (updater || path.length) {
if (accessor === -1) {
obj.push(updater());
} else {
obj[accessor] = setIn(value, path, updater);
return [].concat(_toConsumableArray(nextObj), [setIn([], path, updater)]);
}
} else {
obj.splice(accessor, 1);
var nextValue = setIn(value, path, updater);
if (typeof nextValue !== 'undefined') {
if (nextValue === value) {
return obj;
} else {
nextObj = [].concat(_toConsumableArray(nextObj));
nextObj[accessor] = nextValue;
return nextObj;
}
}
}
return obj;
// If updater returned undefined or no updater at all, delete the item
if (accessor in nextObj) {
nextObj = [].concat(_toConsumableArray(nextObj));
nextObj.splice(accessor, 1);
}
return nextObj;
} else {
if (updater || path.length) {
return _extends({}, obj, _defineProperty({}, accessor, setIn(value, path, updater)));
} else {
var _obj = obj,
deleted = _obj[accessor],
nextObj = _objectWithoutProperties(_obj, [accessor]);
var _nextValue = setIn(value, path, updater);
return nextObj;
if (typeof _nextValue !== 'undefined') {
if (_nextValue === value) {
return obj;
} else {
return _extends({}, nextObj, _defineProperty({}, accessor, _nextValue));
}
}
}
// If updater returned undefined or no updater at all, delete the key
if (accessor in nextObj) {
nextObj = _extends({}, nextObj);
delete nextObj[accessor];
}
return nextObj;
}
}
{
"name": "simple-update-in",
"version": "1.1.2-master.cf20461",
"version": "1.2.0",
"description": "",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -19,10 +19,12 @@ # simple-update-in

For example, `obj.one.two = 1.2`, call `updateIn(obj, ['one', 'two'], 1.2)`. It will return a new object with changes in deep clone.
We share similar signature as [ImmutableJS.updateIn](https://facebook.github.io/immutable-js/docs/#/Map/updateIn):
```js
updateIn(
target: Array|Map,
updateIn<T: Array|Map>(
target: T,
path: (Number|String)[],
updater?: (value: any) => any
)
): T
```

@@ -32,2 +34,4 @@

Like other immutable framework, `updater` is expected to return a new object if there is a change. If the update do not result in a change (triple-equal `===`), then, the original object is returned.
## Example

@@ -65,3 +69,3 @@

You can also use `updateIn` to remove a key by passing a falsy value to the `updater` argument.
You can also use `updateIn` to remove a key by passing a falsy value to the `updater` argument, or return `undefined`.

@@ -78,2 +82,6 @@ ```js

> When removing a non-existing key, the original object will be returned.
The sample code above also works with `updater` returning `undefined`, for example, `updateIn(from, ['two'], () => undefined)`.
## Remove an item in array

@@ -88,2 +96,4 @@

> Also for `updater` returning `undefined`
## Automatic expansion

@@ -98,2 +108,4 @@

> If the `updater` return `undefined`, the object will be untouched.
## Replace incompatible types

@@ -121,2 +133,13 @@

### Corner case
If the target value is of incompatible type, we will convert it to correct type before setting it. In the following sample, the actual value is an empty map instead of the original array.
```js
const from = [0, 1, 2];
const actual = updateIn(from, ['one']);
expect(actual).toEqual({});
```
## Adding an item to array

@@ -128,3 +151,3 @@

const from = [0, 1];
const actual = updateIn(from, [-1], 2);
const actual = updateIn(from, [-1], () => 2);

@@ -134,2 +157,4 @@ expect(actual).toEqual([0, 1, 2]);

> If `updater` returned `undefined`, the value will not be appended.
There is no support on prepend or insertion, however, you can use Rest Operator for array manipulation.

@@ -136,0 +161,0 @@

export default function setIn(obj, path, updater) {
if (!Array.isArray(path)) {
throw new Error('path must be an array');
}
if (!path.length) {

@@ -9,36 +13,62 @@ return updater(obj);

const accessor = path.shift();
let value = typeof obj !== 'undefined' && obj[accessor];
const value = typeof obj !== 'undefined' && obj[accessor];
let nextObj = obj;
if (typeof accessor === 'string' && (typeof obj !== 'object' || Array.isArray(obj))) {
obj = {};
} else if (typeof accessor === 'number' && !Array.isArray(obj)) {
obj = [];
if (typeof accessor === 'string' && (typeof nextObj !== 'object' || Array.isArray(nextObj))) {
nextObj = {};
} else if (typeof accessor === 'number' && !Array.isArray(nextObj)) {
nextObj = [];
}
if (typeof accessor === 'number') {
obj = obj && obj.slice();
if (updater || path.length) {
if (accessor === -1) {
obj.push(updater());
} else {
obj[accessor] = setIn(value, path, updater);
return [...nextObj, setIn([], path, updater)];
}
} else {
obj.splice(accessor, 1);
const nextValue = setIn(value, path, updater);
if (typeof nextValue !== 'undefined') {
if (nextValue === value) {
return obj;
} else {
nextObj = [...nextObj];
nextObj[accessor] = nextValue;
return nextObj;
}
}
}
return obj;
// If updater returned undefined or no updater at all, delete the item
if (accessor in nextObj) {
nextObj = [...nextObj];
nextObj.splice(accessor, 1);
}
return nextObj;
} else {
if (updater || path.length) {
return {
...obj,
[accessor]: setIn(value, path, updater)
};
} else {
const { [accessor]: deleted, ...nextObj } = obj;
const nextValue = setIn(value, path, updater);
return nextObj;
if (typeof nextValue !== 'undefined') {
if (nextValue === value) {
return obj;
} else {
return {
...nextObj,
[accessor]: nextValue
};
}
}
}
// If updater returned undefined or no updater at all, delete the key
if (accessor in nextObj) {
nextObj = { ...nextObj };
delete nextObj[accessor];
}
return nextObj;
}
}

@@ -172,1 +172,85 @@ import updateIn from './index';

});
test('append to array 2', () => {
const from = [0, 1, 2];
const actual = updateIn(from, [-1, 0, 0], () => 3);
expect(from).not.toBe(actual);
expect(actual).toEqual([0, 1, 2, [[3]]]);
});
test('modifying undefined in map', () => {
const from = { one: 1 };
const actual = updateIn(from, ['two', 'three'], value => value && value * 10);
expect(from).toBe(actual);
});
test('modifying undefined in array', () => {
const from = [0, 1, 2, 3];
const actual = updateIn(from, [4], value => value && value * 10);
expect(from).toBe(actual);
});
test('untouched in map', () => {
const from = { one: 1 };
const actual = updateIn(from, ['one'], value => value);
expect(from).toBe(actual);
});
test('untouched in array', () => {
const from = [0, 1, 2];
const actual = updateIn(from, [1], value => value);
expect(from).toBe(actual);
});
test('removing non-existing key in map', () => {
const from = { one: 1 };
const actual = updateIn(from, ['two']);
expect(from).toBe(actual);
});
test('removing non-existing key in array', () => {
const from = [0];
const actual = updateIn(from, [1]);
expect(from).toBe(actual);
});
test('removing using undefined in map', () => {
const from = { one: 1 };
const actual = updateIn(from, ['one'], value => undefined);
expect(actual).toEqual({});
});
test('removing using undefined in array', () => {
const from = [0];
const actual = updateIn(from, [0], value => undefined);
expect(actual).toEqual([]);
});
test('incompatible type and untouched map', () => {
const from = { one: 1 };
const actual = updateIn(from, [0], value => undefined);
expect(actual).toEqual([]);
})
test('incompatible type and untouched array', () => {
const from = [0];
const actual = updateIn(from, ['one'], value => undefined);
expect(actual).toEqual({});
})
test('path not array', () => {
expect(() => {
updateIn({}, 'not valid path');
}).toThrow();
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc