Skip to content

Commit

Permalink
feat: add traverse recursively through the same key
Browse files Browse the repository at this point in the history
  • Loading branch information
rubeniskov committed Nov 23, 2020
1 parent 621dd52 commit 5c27fed
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
42 changes: 34 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const {
createMatcher,
wrapIterator,
entries,
formatJsonPath,
JSONPATH_SEP,
} = require('./utils');

/**
Expand Down Expand Up @@ -133,34 +135,57 @@ const {
* [ '/nested/nested/nested/depth', 3 ]
* [ '/nested/nested/nested/nested/depth', 4 ]
* ```
* __{ [test](#traversejsonoptions--object): "@nested" }__
* ```
* [ '/nested',
* { depth: 1, nested: { depth: 2, nested: [Object] } } ]
* [ '/nested/nested',
* { depth: 2, nested: { depth: 3, nested: [Object] } } ]
* [ '/nested/nested/nested', { depth: 3, nested: { depth: 4 } } ]
* [ '/nested/nested/nested/nested', { depth: 4 } ]
* ```
*/
const traverseJson = (obj, opts) => {
const {
let {
recursive = true,
nested = false,
test = null,
step = 1,
} = { ...opts };

let filter = createMatcher(test);
let rkey;
let filter;
let overall = [];
let cursor = 0;

if (typeof test === 'string' && test[0] === '@') {
rkey = test.substring(1);
nested = true;
filter = false;
} else {
filter = createMatcher(test);
}

const dive = (value, prefix) => {
const remain = overall.slice(cursor + 1);
if (rkey) {
overall = value[rkey] !== undefined
? [[formatJsonPath(prefix, rkey), value[rkey]]]
: [];
} else {
const remain = overall.slice(cursor + 1);

overall = entries(value, prefix);
overall = entries(value, prefix);

for(let i = 0; i < remain.length; i++) {
overall.push(remain[i]);
for(let i = 0; i < remain.length; i++) {
overall.push(remain[i]);
}
cursor = 0;
}
return overall[cursor = 0];
};

dive(obj);

const next = () => {

if (cursor < overall.length) {
let entry = overall[cursor];
if (recursive) {
Expand Down Expand Up @@ -239,3 +264,4 @@ const createIterator = (obj, opts) => {

module.exports = traverseJson;
module.exports.createIterator = createIterator;
module.exports.JSONPATH_SEP = JSONPATH_SEP;
20 changes: 20 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,26 @@ test('should iterate filtering with minimatch through the entries of the given n
iterateEqual(t, ientries, expected, true);
});

test('should iterate recursively through the same key', (t) => {

const expected = [
['/nested', recursiveObject.nested],
['/nested/nested', recursiveObject.nested.nested],
['/nested/nested/nested', recursiveObject.nested.nested.nested],
['/nested/nested/nested/nested', recursiveObject.nested.nested.nested.nested],
];

const merged = {
...recursiveObject, ...nestedObject,
};

const ientries = traverseObject(merged, {
test: '@nested',
});

iterateEqual(t, ientries, expected, true);
});

test('should works as iterable', (t) => {

const { createIterator } = traverseObject;
Expand Down
5 changes: 4 additions & 1 deletion utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const { isPlainObject } = require('is-plain-object');
const minimatch = require('minimatch');

const JSONPATH_SEP = '/';

const isTraversable = (value) => Array.isArray(value) || isPlainObject(value);

const createMatcher = (test) => {
Expand All @@ -15,7 +17,7 @@ const createMatcher = (test) => {
return test && test.test ? ([path]) => test.test(path) : test;
};

const formatJsonPath = (prefix, key) => [prefix, key].join('/');
const formatJsonPath = (prefix, key) => [prefix, key].join(JSONPATH_SEP);

/**
* Wraps a function iteratior to become an iterable
Expand Down Expand Up @@ -45,5 +47,6 @@ module.exports = {
isTraversable,
createMatcher,
wrapIterator,
formatJsonPath,
entries,
};

0 comments on commit 5c27fed

Please sign in to comment.