Skip to content

Commit 44fa393

Browse files
committed
feat!: remove class api and just expose functions
1 parent b6b2141 commit 44fa393

File tree

5 files changed

+145
-142
lines changed

5 files changed

+145
-142
lines changed

README.md

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,40 @@ const div = document.createElement('div');
1717
document.body.appendChild(div);
1818
const startRef = div;
1919

20-
const lt = new LavaTube();
21-
22-
// walk by specifying a visitor function
23-
lt.walk(startRef, visitorFn);
20+
// use "find" when looking for a path to a specific value
21+
const path = LavaTube.find(startRef, target);
22+
23+
// use "walk" to visit every value by specifying a visitor function
24+
// the visitor can return "true" to stop iteration and select the
25+
// current value and path as the final result
26+
const result = LavaTube.walk(startRef, checkValueForTarget);
27+
if (result !== undefined) {
28+
const { value, path } = result;
29+
console.log(`found ${value} at ${path}`)
30+
}
2431

25-
// or using an iterator
26-
for (const [value, path] of lt.iterate(startRef)) {
27-
if (checkValueForTarget(value, path)) {
28-
break;
29-
}
32+
// use "iterate" to get an iterator for visiting values
33+
for (const [value, path] of LavaTube.iterate(startRef)) {
34+
if (checkValueForTarget(value, path)) {
35+
console.log(`found ${value} at ${path}`)
36+
break;
37+
}
3038
}
3139

32-
// new instance with different options
33-
new LavaTube({
34-
maxDepth: 9
35-
}).walk(window, (value, path) => {
36-
// returning true stops iteration
37-
return checkValueForTarget(value, path);
38-
});
40+
// configuration options can be specified as well
41+
const opts = { maxDepth: 9 }
42+
LavaTube.walk(window, (value, path) => {
43+
return checkValueForTarget(value, path);
44+
}, opts);
3945

4046
function checkValueForTarget (value, path) {
41-
if (value === target) {
42-
console.log('found value:', value);
43-
console.log('path to value was:', path);
44-
return true;
45-
}
47+
if (value === target) {
48+
console.log(`found ${value} at ${path}`)
49+
return true;
50+
}
51+
return false;
4652
}
53+
4754
```
4855

4956
### limitations
@@ -54,10 +61,10 @@ However, some values are unreachable without calling functions with certain argu
5461
```javascript
5562
// LavaTube would not be able to access "secret" from just the function "get"
5663
function get(password) {
57-
const secret = {}
58-
if (password === 's3cr3t') {
59-
return secret
60-
}
64+
const secret = {}
65+
if (password === 's3cr3t') {
66+
return secret
67+
}
6168
}
6269
```
6370

@@ -67,14 +74,14 @@ Additionally, property getters and Proxies further complicate object graph explo
6774

6875
```javascript
6976
const obj = {
70-
get abc () {
71-
// returns a new object on every access
72-
return {}
73-
}
77+
get abc () {
78+
// returns a new object on every access
79+
return {}
80+
}
7481
}
7582
const secret = obj.abc
7683
// LavaTube will never see the same value as "secret"
77-
new LavaTube().walk(obj, () => { /* ... */ })
84+
LavaTube.walk(obj, () => { /* ... */ })
7885
```
7986

8087
### install
@@ -85,7 +92,7 @@ new LavaTube().walk(obj, () => { /* ... */ })
8592

8693
```javascript
8794

88-
// options object can be passed as second argument to LavaTube constructor optionally:
95+
// configuration options object:
8996
const opts = {
9097
// a function with which the visited keys during walking
9198
// process can be customizd for how they appear within
@@ -102,7 +109,7 @@ const opts = {
102109
shouldWalk, // [default (target) => true]
103110

104111
// a function that allows you to reveal additional props for a value (if you have more context on its type you might be able to get additional values by calling its methods)
105-
defaultGetAdditionalProps, // [default () => []]
112+
getAdditionalProps, // [default () => []]
106113

107114
// a boolean indicating if we should search depth first instead of breadth first
108115
depthFirst, // [default false]
@@ -114,8 +121,3 @@ const opts = {
114121
realms, // [default [globalThis]]
115122
};
116123
```
117-
118-
### note
119-
120-
A LavaTube instance holds the options to use when walking.
121-
It does not cache visited nodes so it is safe for re-use.

demo/tree/tree.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ export default function tree(src, dst, limit) {
2020
}
2121

2222
const tree = {};
23-
new LavaTube({
23+
LavaTube.walk(src, eachValue, {
2424
generateKey: key,
2525
maxDepth: limit,
26-
}).walk(src, eachValue);
26+
});
2727
return tree;
2828
}
2929

demo/walkAndSearch/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function showResult (start, end, result) {
1515

1616
function walkAndSearch(start, end){
1717
let result = false;
18-
new LavaTube().walk(start, (val) => {
18+
LavaTube.walk(start, (val) => {
1919
return result = result || val === end;
2020
});
2121
return result;

src/index.js

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,31 @@ function* iterateAndTrack (subTree, tracker) {
322322
}
323323
}
324324

325+
const makeConfig = ({
326+
generateKey = (key, value) => key,
327+
shouldInvokeGetters = true,
328+
maxDepth = Infinity,
329+
shouldWalk = () => true,
330+
getAdditionalProps = () => [],
331+
depthFirst = false,
332+
exhaustiveWeakMapSearch = false,
333+
realms = [{ Map, Set, WeakMap }],
334+
} = {}) => {
335+
return {
336+
generateKey,
337+
shouldInvokeGetters,
338+
maxDepth,
339+
shouldWalk,
340+
getAdditionalProps,
341+
depthFirst,
342+
exhaustiveWeakMapSearch,
343+
realms,
344+
};
345+
}
325346

326-
function* walkIterativelyPublic (target, config, visited = new Set(), path = []) {
347+
function* walkIterativelyEntry (target, opts, visited = new Set(), path = []) {
327348
const depth = 0
349+
const config = makeConfig(opts);
328350

329351
if (!shouldVisit(target, visited, config.shouldWalk)) {
330352
return;
@@ -384,44 +406,46 @@ const walkIteratively = function*(target, config, depth, visited, path) {
384406
}
385407
}
386408

387-
export default class LavaTube {
388-
constructor({
389-
generateKey = (key, value) => key,
390-
shouldInvokeGetters = true,
391-
maxDepth = Infinity,
392-
shouldWalk = () => true,
393-
getAdditionalProps = () => [],
394-
depthFirst = false,
395-
exhaustiveWeakMapSearch = false,
396-
realms = [{ Map, Set, WeakMap }],
397-
} = {}) {
398-
this.config = {
399-
depthFirst,
400-
shouldWalk,
401-
shouldInvokeGetters,
402-
generateKey,
403-
getAdditionalProps,
404-
exhaustiveWeakMapSearch,
405-
maxDepth,
406-
realms,
407-
};
408-
}
409+
// public API
409410

410-
walk (start, visitorFn) {
411-
for (const [value, path] of walkIterativelyPublic(
412-
start,
413-
this.config,
414-
)) {
415-
if (visitorFn(value, path)) {
416-
return true;
417-
}
411+
export const iterate = (start, opts) => {
412+
return walkIterativelyEntry(start, opts);
413+
}
414+
415+
export const walk = (start, visitorFn, opts) => {
416+
for (const [value, path] of walkIterativelyEntry(
417+
start,
418+
opts,
419+
)) {
420+
if (visitorFn(value, path)) {
421+
return { value, path };
418422
}
419423
}
424+
}
425+
426+
export const getAllValues = (start, opts) => {
427+
const results = [];
428+
walk(start, (value) => {
429+
results.push(value);
430+
}, opts);
431+
return results;
432+
}
420433

421-
iterate (start) {
422-
return walkIterativelyPublic(
423-
start,
424-
this.config,
425-
);
434+
export const find = (start, target, opts) => {
435+
const result = walk(start, (value) => {
436+
if (value === target) {
437+
return true;
438+
}
439+
}, opts);
440+
if (result !== undefined) {
441+
return result.path;
426442
}
443+
return undefined;
444+
}
445+
446+
export default {
447+
iterate,
448+
walk,
449+
getAllValues,
450+
find,
427451
}

0 commit comments

Comments
 (0)