object-path-immutable
Advanced tools
Comparing version 0.5.1 to 0.5.2
@@ -150,2 +150,9 @@ /* globals define */ | ||
api.update = function update (dest, src, path, updater) { | ||
return changeImmutable(dest, src, path, function (clonedObj, finalPath) { | ||
clonedObj[finalPath] = updater(clonedObj[finalPath]) | ||
return clonedObj | ||
}) | ||
} | ||
api.push = function push (dest, src, path /*, values */) { | ||
@@ -152,0 +159,0 @@ var values = Array.prototype.slice.call(arguments, 3) |
{ | ||
"name": "object-path-immutable", | ||
"version": "0.5.1", | ||
"version": "0.5.2", | ||
"description": "Modify deep object properties without modifying the original object (immutability). Works great with React and Redux.", | ||
@@ -5,0 +5,0 @@ "author": "Mario Casciaro <mariocasciaro@gmail.com>", |
232
README.md
@@ -0,31 +1,27 @@ | ||
[![build](https://img.shields.io/travis/mariocasciaro/object-path-immutable.svg?style=flat-square)](https://travis-ci.org/mariocasciaro/object-path-immutable) | ||
[![coverage](https://img.shields.io/coveralls/mariocasciaro/object-path-immutable.svg?style=flat-square)](https://coveralls.io/r/mariocasciaro/object-path-immutable) | ||
[![downloads](https://img.shields.io/npm/dm/object-path-immutable.svg?style=flat-square)](https://www.npmjs.com/package/object-path-immutable) | ||
[![version](https://img.shields.io/npm/v/object-path-immutable.svg?style=flat-square)](https://www.npmjs.com/package/object-path-immutable) | ||
[![devdeps](https://img.shields.io/david/dev/mariocasciaro/object-path-immutable.svg?style=flat-square)](https://david-dm.org/mariocasciaro/object-path-immutable#info=devDependencies) | ||
object-path-immutable | ||
=========== | ||
Tiny JS library to modify deep object properties without modifying the original object (immutability). | ||
Tiny JS library to modify deep object properties without modifying the original object (immutability). | ||
Works great with React (especially when using `setState()`) and Redux (inside a reducer). | ||
This can be seen as a simpler and more intuitive alternative to the *React Immutability Helpers* and *Immutable.js* | ||
This can be seen as a simpler and more intuitive alternative to the *React Immutability Helpers* and *Immutable.js*. | ||
[![NPM version](https://badge.fury.io/js/object-path-immutable.png)](http://badge.fury.io/js/object-path-immutable) | ||
[![Build Status](https://travis-ci.org/mariocasciaro/object-path-immutable.png)](https://travis-ci.org/mariocasciaro/object-path-immutable) | ||
[![Coverage Status](https://coveralls.io/repos/mariocasciaro/object-path-immutable/badge.png)](https://coveralls.io/r/mariocasciaro/object-path-immutable) | ||
[![devDependency Status](https://david-dm.org/mariocasciaro/object-path-immutable/dev-status.svg)](https://david-dm.org/mariocasciaro/object-path-immutable#info=devDependencies) | ||
![Downloads](http://img.shields.io/npm/dm/object-path-immutable.svg) | ||
## Install | ||
### Node.js | ||
npm install object-path-immutable --save | ||
``` | ||
npm install object-path-immutable --save | ||
``` | ||
## Quick usage | ||
The following, sets a property without modifying the original object. | ||
It will minimize the number of clones down the line. The resulting object is just a plain JS object literal, | ||
The following, sets a property without modifying the original object. | ||
It will minimize the number of clones down the line. The resulting object is just a plain JS object literal, | ||
so be warned that it will not be protected against property mutations (like `Immutable.js`) | ||
```javascript | ||
var obj = { | ||
const obj = { | ||
a: { | ||
@@ -37,26 +33,30 @@ b: 'c', | ||
//set a deep property | ||
var newObj = immutable.set(obj, 'a.b', 'f') | ||
//returns | ||
//var obj = { | ||
// a: { | ||
// b: 'f', | ||
// c: ['d', 'f'] | ||
// } | ||
//} | ||
const newObj = immutable.set(obj, 'a.b', 'f') | ||
// { | ||
// a: { | ||
// b: 'f', | ||
// c: ['d', 'f'] | ||
// } | ||
// } | ||
//obj !== newObj | ||
//obj.a !== newObj.a | ||
//obj.b !== newObj.b | ||
// obj !== newObj | ||
// obj.a !== newObj.a | ||
// obj.b !== newObj.b | ||
//However: | ||
//obj.c === newObj.c | ||
// However: | ||
// obj.c === newObj.c | ||
``` | ||
Note that you can also chain the api's and call `value()` at the end to retrieve the resulting object. | ||
```javascript | ||
const newObj = immutable(obj).set('a.b', 'f').del('a.c.0').value() | ||
``` | ||
## API | ||
```javascript | ||
// Premises | ||
var obj = { | ||
const obj = { | ||
a: { | ||
@@ -68,75 +68,125 @@ b: 'c', | ||
var immutable = require("object-path-immutable") | ||
import immutable from 'object-path-immutable' | ||
``` | ||
//set deep property | ||
var newObj = immutable.set(obj, 'a.b', 'f') | ||
//returns | ||
//var obj = { | ||
// a: { | ||
// b: 'f', | ||
// c: ['d', 'f'] | ||
// } | ||
//} | ||
#### set (initialObject, path, value) | ||
//it can also use an array to describe the path | ||
var newObj = immutable.set(obj, ['a', 'b'], 'f') | ||
Changes an object property. | ||
//if the path is specified as a string, then numbers are automatically interpreted as array indexes | ||
var newObj = immutable.set(obj, 'a.c.1', 'fooo') | ||
//returns | ||
//var obj = { | ||
// a: { | ||
// b: 'f', | ||
// c: ['d', 'fooo'] | ||
// } | ||
//} | ||
- Path can be either a string or an array. | ||
```javascript | ||
const newObj1 = immutable.set(obj, 'a.b', 'f') | ||
const newObj2 = immutable.set(obj, ['a', 'b'], 'f') | ||
const newObj3 = immutable.set(obj, ['a', 'b'], v => 'f') | ||
//push into a deep array (it will create intermediate objects/arrays if necessary) | ||
var newObj = immutable.push(obj, 'a.d', 'f') | ||
//returns | ||
//var obj = { | ||
// a: { | ||
// b: 'f', | ||
// c: ['d', 'f'], | ||
// d: ['f'] | ||
// } | ||
//} | ||
// { | ||
// a: { | ||
// b: 'f', | ||
// c: ['d', 'f'] | ||
// } | ||
// } | ||
//delete a deep property | ||
var newObj = immutable.del(obj, 'a.c') | ||
//returns | ||
//var obj = { | ||
// a: { | ||
// b: 'f' | ||
// } | ||
//} | ||
// Note that if the path is specified as a string, numbers are automatically interpreted as array indexes. | ||
//delete a deep array item (splice) | ||
var newObj = immutable.del(obj, 'a.c.0') | ||
//var obj = { | ||
// a: { | ||
// b: 'f', | ||
// c: ['f'] | ||
// } | ||
//} | ||
const newObj = immutable.set(obj, 'a.c.1', 'fooo') | ||
// { | ||
// a: { | ||
// b: 'f', | ||
// c: ['d', 'fooo'] | ||
// } | ||
// } | ||
``` | ||
//shallow copy properties | ||
var newObj = immutable.assign(obj, 'a', { b: 'f', g: 'h' }) | ||
//returns | ||
//var obj = { | ||
// a: { | ||
// b: 'f', | ||
// c: ['d, 'f'], | ||
// g: 'h' | ||
// } | ||
//} | ||
#### update (initialObject, path, updater) | ||
//Chaining mode. value() at the end of the chain is used to retrieve the resulting object | ||
var newObj = immutable(obj).set('a.b', 'f').del('a.c.0').value() | ||
Updates an object property. | ||
```javascript | ||
const obj = { | ||
a: { | ||
b: 1, | ||
}, | ||
} | ||
const newObj = immutable.update(obj, ['a', 'b'], v => v + 1) | ||
// { | ||
// a: { | ||
// b: 2, | ||
// } | ||
// } | ||
``` | ||
## Equivalent library with side effects | ||
#### push (initialObject, path, value) | ||
Push into a deep array (it will create intermediate objects/arrays if necessary). | ||
```javascript | ||
const newObj = immutable.push(obj, 'a.d', 'f') | ||
// { | ||
// a: { | ||
// b: 'f', | ||
// c: ['d', 'f'], | ||
// d: ['f'] | ||
// } | ||
// } | ||
``` | ||
#### delete (initialObject, path) | ||
Deletes a property. | ||
```javascript | ||
const newObj = immutable.del(obj, 'a.c') | ||
// { | ||
// a: { | ||
// b: 'f' | ||
// } | ||
// } | ||
``` | ||
Can also delete a deep array item using splice | ||
```javascript | ||
const newObj = immutable.del(obj, 'a.c.0') | ||
// { | ||
// a: { | ||
// b: 'f', | ||
// c: ['f'] | ||
// } | ||
// } | ||
``` | ||
##### assign (initialObject, path, payload) | ||
Shallow copy properties. | ||
```javascript | ||
const newObj = immutable.assign(obj, 'a', { b: 'f', g: 'h' }) | ||
// { | ||
// a: { | ||
// b: 'f', | ||
// c: ['d, 'f'], | ||
// g: 'h' | ||
// } | ||
// } | ||
``` | ||
##### insert (initialObject, path, payload, position) | ||
Insert property at the specific array index. | ||
```javascript | ||
const newObj = immutable.insert(obj, 'a.c', 'k', 1) | ||
// var obj = { | ||
// a: { | ||
// b: 'c', | ||
// c: ['d, 'k' 'f'], | ||
// } | ||
// } | ||
``` | ||
### Equivalent library with side effects | ||
[object-path](https://github.com/mariocasciaro/object-path) | ||
@@ -143,0 +193,0 @@ |
36
test.js
@@ -75,2 +75,25 @@ /* globals describe, it */ | ||
}) | ||
it('should update a deep key', function () { | ||
var obj = { | ||
a: { | ||
b: 1 | ||
}, | ||
c: { | ||
d: 2 | ||
} | ||
} | ||
var newObj = op.update(obj, 'a.b', function (value) { | ||
return value + 1 | ||
}) | ||
expect(newObj).not.to.be.equal(obj) | ||
expect(newObj.a).not.to.be.equal(obj.a) | ||
expect(obj.a).to.be.eql({b: 1}) | ||
// this should be the same | ||
expect(newObj.c).to.be.equal(obj.c) | ||
expect(newObj.a.b).to.be.equal(2) | ||
}) | ||
}) | ||
@@ -354,3 +377,5 @@ | ||
var newObj = op(obj).set('a.q', 'q').del('a.d').value() | ||
var newObj = op(obj).set('a.q', 'q').del('a.d').update('a.f', function (v) { | ||
return v + 1 | ||
}).value() | ||
@@ -361,3 +386,3 @@ expect(newObj).not.to.be.equal(obj) | ||
expect(newObj.a).to.be.eql({f: 2, q: 'q'}) | ||
expect(newObj.a).to.be.eql({f: 3, q: 'q'}) | ||
}) | ||
@@ -397,2 +422,9 @@ | ||
expect(function () { | ||
/* istanbul ignore next */ | ||
transaction.update('foo', function (v) { | ||
return v + 'bar' | ||
}) | ||
}).to.throw() | ||
expect(function () { | ||
transaction.assign('frob', { | ||
@@ -399,0 +431,0 @@ nard: 23 |
21641
526
195