set-object-path
Advanced tools
Comparing version 0.0.0 to 2.0.0
80
index.js
@@ -1,68 +0,38 @@ | ||
/** | ||
* This is a HOF that is used by our React components to build onChange handlers | ||
* for a given key path into the model. | ||
*/ | ||
module.exports = updatePath | ||
module.exports = set; | ||
function updatePath (path, value) { | ||
path = toPath(path) | ||
var curr = this | ||
var last = path.length - 1 | ||
for (var i = 0; i < last; i++) { | ||
var k = path[i] | ||
if (!curr[k]) { | ||
if (typeof path[i + 1] === 'number') { | ||
curr = curr[k] = [] | ||
} else { | ||
curr = curr[k] = {} | ||
} | ||
} else { | ||
curr = curr[k] | ||
} | ||
function set (context, path, value) { | ||
if (path.indexOf('.') == -1 && path.indexOf('[') == -1) { | ||
context[path] = value; | ||
return; | ||
} | ||
curr[path[last]] = value | ||
} | ||
updatePath.bind = function (o, path, value) { | ||
if (typeof o !== 'object') { | ||
throw new TypeError('setPath must be bound to an object') | ||
} | ||
var updatePath = this | ||
if (path && value) | ||
return function () { updatePath.call(o, path, value) } | ||
else if (path) | ||
return function (value) { updatePath.call(o, path, value) } | ||
var crumbs = parseCrumbs(path); | ||
var i = -1; | ||
var len = crumbs.length; | ||
var result; | ||
var fn = function (path, value) { updatePath.call(o, path, value) } | ||
fn.setter = updatePath.setter | ||
fn.prefix = updatePath.prefix | ||
return fn | ||
} | ||
while (++i < len) { | ||
if (crumbs[i].length == 0) continue; | ||
updatePath.setter = function (path) { | ||
var updatePath = this | ||
return function (value) { | ||
updatePath.call(this, path, value) | ||
} | ||
} | ||
if (i + 1 < len && context[crumbs[i]] == undefined) { | ||
context[crumbs[i]] = {}; | ||
} | ||
updatePath.prefix = function (prefix) { | ||
var updatePath = this | ||
prefix = toPath(prefix) | ||
prefixedUpdatePath.setter = function (path) { | ||
path = prefix.concat(toPath(path)) | ||
return function (value) { | ||
updatePath.call(this, path, value) | ||
if (i + 1 < len) { | ||
context = context[crumbs[i]]; | ||
continue; | ||
} | ||
context[crumbs[i]] = value; | ||
} | ||
} | ||
return prefixedUpdatePath | ||
function parseCrumbs (path) { | ||
var crumbs = path.split(/\.|\[|\]/g); | ||
function prefixedUpdatePath (path, value) { | ||
updatePath.call(this, prefix.concat(toPath(path)), value) | ||
if (crumbs[crumbs.length - 1] == "") { | ||
crumbs = crumbs.slice(0, -1); | ||
} | ||
} | ||
function toPath (it) { | ||
return (typeof it === 'string') ? it.split('.') : it | ||
return crumbs; | ||
} |
{ | ||
"name": "set-object-path", | ||
"version": "0.0.0", | ||
"description": "functions for setting values deep insde nested objects", | ||
"version": "2.0.0", | ||
"description": "Set given (deep) object path", | ||
"main": "index.js", | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"tape": "~2.3.2", | ||
"markdown-code-blocks": "0.0.1" | ||
}, | ||
"scripts": { | ||
"test": "markdown-code-blocks -t javascript < README.md | node" | ||
"test": "node test" | ||
}, | ||
"keywords": [ | ||
"object", | ||
"path", | ||
"change", | ||
"set object path" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/grncdr/js-update-path.git" | ||
"url": "git@github.com:azer/set-object-path.git", | ||
"type": "git" | ||
}, | ||
"bugs": { | ||
"type": "git", | ||
"url": "git://github.com/grncdr/js-update-path/issues" | ||
}, | ||
"homepage": "https://github.com/grncdr/js-update-path", | ||
"keywords": [], | ||
"author": "Stephen Sugden <me@stephensugden.com>", | ||
"license": "MIT" | ||
"author": "azer", | ||
"license": "BSD", | ||
"devDependencies": { | ||
"prova": "^2.1.2" | ||
} | ||
} |
105
README.md
@@ -1,94 +0,27 @@ | ||
# set-object-path | ||
## set-object-path | ||
Functions for setting values deep insde nested objects. | ||
Set given (deep) object path | ||
I use this for generating callbacks that can modify data in a restricted scope | ||
of a larger object. | ||
See also: [get-object-path](http://github.com/azer/get-object-path), [change-object](http://github.com/azer/change-object) | ||
## Synopsis | ||
## Install | ||
```javascript | ||
var test = require('tape') | ||
var setPath = require('./') | ||
```bash | ||
$ npm install set-object-path | ||
``` | ||
test('use .call to pass root object', function (t) { | ||
var o = {} | ||
setPath.call(o, 'a.b.c', 2) | ||
t.deepEqual(o, {a: {b: {c: 2}}}) | ||
t.end() | ||
}) | ||
## Usage | ||
test('use array-paths instead of dot-separated strings', function (t) { | ||
var o = {} | ||
setPath.call(o, ['people', 'Mr. Jones'], "is back") | ||
t.deepEqual(o, { | ||
people: { | ||
'Mr. Jones': 'is back' | ||
} | ||
}) | ||
t.end() | ||
}) | ||
```js | ||
var set = require('set-object-path') | ||
var data = { | ||
title: 'My Products', | ||
products: { | ||
eggs: [{ kind: 'white', amount: 300 }, { kind: 'brown', amount: 200 }] | ||
} | ||
} | ||
test('use .setter to pass path implicitly', function (t) { | ||
var setName = setPath.setter('name') | ||
var my = {} | ||
setName.call(my, 'Stephen') | ||
t.equal(my.name, 'Stephen') | ||
t.end() | ||
}) | ||
test('use .bind to pass root implicitly', function (t) { | ||
var my = {} | ||
var set = setPath.bind(my) | ||
set('name', 'Stephen') | ||
t.equal(my.name, 'Stephen') | ||
t.end() | ||
}) | ||
test('chain .bind and .setter for awesomeness', function (t) { | ||
var my = {} | ||
var setMyName = setPath.setter('name').bind(my) | ||
setMyName('Stephen') | ||
t.equal(my.name, 'Stephen') | ||
// or do it the other way around | ||
setPath.bind(my).setter('name')('Still Stephen') | ||
t.equal(my.name, 'Still Stephen') | ||
t.end() | ||
}) | ||
test('use .prefix to limit the scope of allowed changes', function (t) { | ||
var model = {} | ||
var setApples = setPath.prefix('apples').bind(model) | ||
var setOranges = setPath.prefix('oranges').bind(model) | ||
setApples('count', 1) | ||
setOranges('count', 2) | ||
t.deepEqual(model, { | ||
apples: { count: 1 }, | ||
oranges: { count: 2 }, | ||
}) | ||
t.end() | ||
}) | ||
test('chain .bind, .prefix, .setter', function (t) { | ||
var model = {} | ||
var setAppleCount = setPath.bind(model).prefix('apples').setter('count') | ||
var setOrangeCount = setPath.bind(model).prefix('oranges').setter('count') | ||
setAppleCount(3) | ||
setOrangeCount(4) | ||
t.deepEqual(model, { | ||
apples: { count: 3 }, | ||
oranges: { count: 4 }, | ||
}) | ||
t.end() | ||
}) | ||
set(data, 'products.eggs[0].amount', 200) | ||
data.products.eggs[0].amount | ||
// => 200 | ||
``` | ||
## Install | ||
npm install set-object-path | ||
## License | ||
MIT |
Misc. License Issues
License(Experimental) A package's licensing information has fine-grained problems.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1
1673
1
29
2
28