npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@lavamoat/lavatube

v1.0.0

Published

lavatube

Downloads

91

Readme

LavaTube

Javascript object graph walker. Tries to reach every possible value from a starting reference.

demo

check out the demo

usage

import LavaTube from '@lavamoat/lavatube';

// get starting and target references for your search
const target = window;
const div = document.createElement('div');
document.body.appendChild(div);
const startRef = div;

// use "find" when looking for a path to a specific value
const path = LavaTube.find(startRef, target);

// use "walk" to visit every value by specifying a visitor function
// the visitor can return "true" to stop iteration and select the
// current value and path as the final result
const result = LavaTube.walk(startRef, checkValueForTarget);
if (result !== undefined) {
  const { value, path } = result;
  console.log(`found ${value} at ${path}`)
}

// use "iterate" to get an iterator for visiting values
for (const [value, path] of LavaTube.iterate(startRef)) {
  if (checkValueForTarget(value, path)) {
    console.log(`found ${value} at ${path}`)
    break;
  }
}

// configuration options can be specified as well
const opts = { maxDepth: 9 }
LavaTube.walk(window, (value, path) => {
  return checkValueForTarget(value, path);
}, opts);

function checkValueForTarget (value, path) {
  if (value === target) {
    console.log(`found ${value} at ${path}`)
    return true;
  }
  return false;
}

limitations

LavaTube works by walking the object graph, including properties and prototypes. However, some values are unreachable without calling functions with certain arguments.

// LavaTube would not be able to access "secret" from just the function "get"
function get(password) {
  const secret = {}
  if (password === 's3cr3t') {
    return secret
  }
}

LavaTube does its best to find every value it can, but consider a negative search result to be "inconclusive" and not a proof of unreachability. See this post for an idea of how something can still be reachable through esoteric means.

Additionally, property getters and Proxies further complicate object graph exploration. They can to return a new value on each access and can also trigger other side effects like adding new properties on objects we've already visited.

const obj = {
  get abc () {
    // returns a new object on every access
    return {}
  }
}
const secret = obj.abc
// LavaTube will never see the same value as "secret"
LavaTube.walk(obj, () => { /* ... */ })

install

yarn add @lavamoat/lavatube / npm install @lavamoat/lavatube

options


// configuration options object:
const opts = {
    // a boolean indicating we should invoke getters
    shouldInvokeGetters, //[default: true]

    // a boolean indicating if we should attempt to call all visited functions (with no arguments).
    shouldCallFunctions, // [default: false]

    // a boolean indicating if we should attempt to construct (new Thing()) all visited functions (with no arguments).
    shouldConstructFunctions, // [default: false]

    // we cant iterate WeakMaps on their own, but we can take every value that we find and try it as a key each WeakMap
    shouldBruteForceWeakMaps, // [default: false]

    // a function that allows you to skip walking the provided value
    shouldWalk, // [default: (target) => true]

    // a number to indicate the maximum recursion depth LavaTube is allowed to walk.
    maxDepth, // [default: Infinity]

    // a boolean indicating if we should search depth first instead of breadth first.
    // potentially useful when looking for a distantly connected value
    depthFirst, // [default: false]

    // 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)
    getAdditionalProps, // [default: () => []]

    // when dealing with multiple Realms (eg browser: iframes, node: vms), we cant inspect Maps, Sets, or WeakMaps without knowing about the other Realm's named intrinsics. This option allows you to specify all known Realm globalThis objects.
    globalThese, // [default: [globalThis]]

    // a function for modifying how the path segment strings are generated.
    generateKey, // [default: (key, value) => key]
};