Comparing version 1.0.1 to 1.0.2
'use strict' | ||
const Readable = require('stream').Readable | ||
function keys (obj, res) { | ||
if (typeof obj !== 'object') throw new TypeError(`'obj' parameter must be of type object.`) | ||
res = res || [] | ||
@@ -17,2 +19,3 @@ Object.keys(obj).forEach((k) => { | ||
function vals (obj, res) { | ||
if (typeof obj !== 'object') throw new TypeError(`'obj' parameter must be of type object.`) | ||
res = res || [] | ||
@@ -30,20 +33,53 @@ Object.keys(obj).forEach((k) => { | ||
function find (obj, key, res) { | ||
function key (obj) { | ||
if (typeof obj !== 'object') throw new TypeError(`'obj' parameter must be of type object.`) | ||
return Object.keys(obj)[0] | ||
} | ||
function find (obj, keyterm, res) { | ||
if (typeof obj !== 'object') throw new TypeError(`'obj' parameter must be of type object.`) | ||
if (typeof keyterm !== 'string') throw new TypeError(`'key' parameter must be of type string.`) | ||
res = res || [] | ||
if (typeof key !== 'string') throw new TypeError(`'key' parameter must be of type string.`) | ||
Object.keys(obj).forEach((k) => { | ||
if (typeof obj[k] === 'object') { | ||
if (!(/^\d+$/.test(k)) && (k === key)) res.push({[k]: obj[k]}) | ||
res = find(obj[k], key, res) | ||
} else { | ||
if (!(/^\d+$/.test(k)) && (k === key)) res.push({[k]: obj[k]}) | ||
} | ||
vals(obj).forEach((i) => { | ||
if (key(i) === keyterm) res.push(i[key(i)]) | ||
}) | ||
return res | ||
if (res.length === 1) { | ||
return res[0] | ||
} else { | ||
return res | ||
} | ||
} | ||
class Rstream extends Readable { | ||
constructor (opt) { | ||
super(opt) | ||
if (typeof opt.obj !== 'object') throw new TypeError(`'obj' parameter must be of type object.`) | ||
opt = Object.assign(opt, {objectMode: true}) | ||
this.opt = opt | ||
this._obj = opt.obj | ||
} | ||
_read () { | ||
vals(this._obj).forEach((i) => { | ||
if (i === null) { | ||
process.nextTick(() => this.emit('error', new Error('null object'))) | ||
return | ||
} else { | ||
var dat = {key: key(i), val: i[key(i)]} | ||
this.push(dat) | ||
} | ||
}) | ||
this.push(null) | ||
} | ||
} | ||
function readStream (obj) { | ||
return new Rstream({obj: obj}) | ||
} | ||
module.exports = { | ||
keys: keys, | ||
vals: vals, | ||
find: find | ||
find: find, | ||
key: key, | ||
readStream: readStream | ||
} |
{ | ||
"name": "deeputil", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"description": "tiny recursive utility to deal with keys/values of deeply nested objects", | ||
"main": "deeputil.js", | ||
"scripts": { | ||
"test": "./node_modules/.bin/mocha --reporter spec test/" | ||
"test": "standard ./deeputil.js && mocha" | ||
}, | ||
@@ -27,5 +27,5 @@ "repository": { | ||
"homepage": "https://github.com/mawni/deeputil#readme", | ||
"devDependencies": { | ||
"mocha": "^3.1.2" | ||
"engines": { | ||
"node": ">=4.0.0" | ||
} | ||
} |
154
README.md
@@ -5,61 +5,23 @@ #deeputil | ||
<a href="https://github.com/feross/standard"><img src="https://cdn.rawgit.com/feross/standard/master/sticker.svg" alt="Standard JavaScript" width="100"></a> | ||
`deeputil` is a tiny [node.js](https://nodejs.org) module that provides a few recursive functions for dealing with keys/values of deeply nested objects. | ||
###install | ||
###Install | ||
`npm i deeputil` | ||
###docs | ||
###Docs | ||
*a dummy object for use in examples below* | ||
**deeputil.key(obj)** | ||
* `obj` `{Object}` | ||
* `@return` `{String}` the property name of `obj` | ||
```javascript | ||
var testobj = { | ||
"rname": "gonzo", | ||
"rid": 274, | ||
"rdata": [ | ||
{ | ||
"username": "", | ||
"email": "", | ||
"msgs": [] | ||
}, | ||
{ | ||
"username": "gonzo", | ||
"email": "gonzoemail", | ||
"msgs": [ | ||
{ | ||
"msgid": 19, | ||
"msg": "explore your mind", | ||
"sen": "anonym", | ||
"time": "" | ||
} | ||
] | ||
} | ||
], | ||
"complx": { | ||
"somearr": ["wolf", "octopus", "epsilon"], | ||
"langs": { | ||
"js": { | ||
"jsobj": { | ||
"djsobj": { | ||
"ddjsobj": { | ||
"dddjsobj": "alright" | ||
} | ||
} | ||
}, | ||
"fun": "for sure" | ||
}, | ||
"shell": { | ||
"shellobj": { | ||
"dshellobj": "nice" | ||
} | ||
}, | ||
"go": { | ||
"gobj": { | ||
"dgobj": ["pretty", "cool"] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
const du = require('deeputil') | ||
var someobj = {username: 'foo'} | ||
console.log(du.key(someobj)) | ||
// result -> 'username' | ||
``` | ||
@@ -72,3 +34,3 @@ | ||
returns an array of all the keys of the given object no matter what! | ||
returns an array of all the keys of `obj` no matter how deeply nested! | ||
@@ -78,9 +40,6 @@ ```javascript | ||
console.log(du.keys(testobj)) | ||
/* will return | ||
["rname","rid","rdata","username","email","msgs","msgid", | ||
"msg","sen","time","complx","somearr","langs","js","jsobj", | ||
"djsobj","ddjsobj","dddjsobj","fun","shell","shellobj", | ||
"dshellobj","go","gobj","dgobj"] | ||
*/ | ||
var someobj = { | ||
... | ||
} | ||
console.dir(du.keys(someobj)) | ||
``` | ||
@@ -93,3 +52,3 @@ | ||
returns an array of all the key/value pairs of the given object. | ||
returns an array of all the key/value pairs of `obj`. | ||
@@ -99,41 +58,68 @@ ```javascript | ||
console.log(du.vals(testobj)) | ||
var someobj = { | ||
... | ||
} | ||
console.dir(du.vals(someobj)) | ||
``` | ||
**deeputil.find(obj, key)** | ||
**deeputil.readStream(obj)** | ||
* `obj` `{Object}` object to find items in | ||
* `key` `{String}` the key to find | ||
* `@return` `{Array<Object>}` | ||
* `obj` `{Object}` | ||
* `@return` {[stream.Readable](https://nodejs.org/api/stream.html#stream_class_stream_readable)} a readable stream | ||
returns an array of results if any, otherwise returns an empty array. If more than one item with the same key found (like in an array), the result array contains all of them. | ||
* `data` `{Object}` `{key:'', val: }` | ||
streams all key/value pairs of `obj` | ||
```javascript | ||
const du = require('deeputil') | ||
// find 'ddjsobj' | ||
console.log('%j', du.find(testobj, 'djsobj')) | ||
/* will return | ||
[{"djsobj":{"ddjsobj":{"dddjsobj":"alright"}}}] | ||
*/ | ||
var someobj = { | ||
... | ||
} | ||
du.readStream(someobj).on('error', (err) => { | ||
console.error(err) | ||
}).on('data', (dat) => { | ||
console.log('key:', dat.key) | ||
console.log('value:', dat.val) | ||
}).on('end', () => { | ||
console.log('finished successfully.') | ||
}) | ||
``` | ||
```javascript | ||
const du = require('deeputil') | ||
**deeputil.find(obj, key)** | ||
// find 'dgobj' | ||
console.log(du.find(testobj, 'dgobj')) | ||
/* will return | ||
[ { dgobj: [ 'pretty', 'cool' ] } ] | ||
*/ | ||
``` | ||
* `obj` `{Object}` | ||
* `key` `{String}` the key to find its corresponding value | ||
* `@return` `{typeof found value | Array<typeof found value>}` | ||
* if only one item found, returns the found value | ||
* if more than one item with the same key found (like in an array), returns an array of found values | ||
```javascript | ||
const du = require('deeputil') | ||
// find 'username' | ||
console.log(du.find(testobj, 'username')) | ||
/* will return | ||
[ { username: '' }, { username: 'gonzo' } ] | ||
*/ | ||
var someobj = { | ||
data: [{username:'plugh', id: 17}, {username: 'thud', id: 92}], | ||
baz: { | ||
qux: { | ||
garply: 'waldo', | ||
quux: ['corge', 'grault'] | ||
} | ||
} | ||
} | ||
console.log(du.find(someobj, 'qux')) | ||
// result -> { garply: 'waldo', quux: [ 'corge', 'grault' ] } | ||
console.log(du.find(someobj, 'garply')) | ||
// result -> waldo | ||
console.log(du.find(someobj, 'quux')) | ||
// result -> [ 'corge', 'grault' ] | ||
console.log(du.find(someobj, 'username')) | ||
// result -> [ 'plugh', 'thud' ] | ||
``` | ||
6600
0
76
121