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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@devframes/plugin-data-inspector

v1.2.5

Published

Devframe plugin for inspecting live server objects interactively with jora queries.

Downloads

75,362

Readme

@devframes/plugin-data-inspector

Inspect live server-side objects interactively. Other devframes and host frameworks register data sources; the workbench composes jora queries against them (executed in the process that owns the objects) and renders normalized results in a discovery.js struct view with type badges, a shape panel, saved queries, and shareable URL state. Deep graphs expand a level at a time (load deeper fetches each subtree on demand), an optional poller re-runs the query every N seconds, and a toolbar offers expand/collapse-all and copy.

Register a data source

The registry is process-global: register from anywhere, before or after the devframe mounts:

import { registerDataSource } from '@devframes/plugin-data-inspector/registry'

registerDataSource({
  id: 'my-plugin:state',
  title: 'My plugin state',
  description: 'The live state store',
  data: () => store, // value or (async) factory; `static: true` memoizes
  queries: [{ title: 'Active entries', query: 'entries.mapEntries()' }],
})

Devframes that prefer zero package dependency consume the same store through the typed context service:

ctx.services.whenAvailable('devframes:plugin:data-inspector:sources', (sources) => {
  sources.register({ id: 'my-plugin:state', title: 'My state', data: () => store })
})

Writable sources

Sources opt into live edits with writable: true: on the root view ($), every value grows an edit affordance that opens a side panel where you set a value (string / number / boolean / null / undefined / JSON), add or delete entries, or rename keys; the mutation is applied in place to the live object through the write RPC. Read-only stays the default; static: true sources are memoized snapshots and always stay read-only (declaring both reports DP_DATA_INSPECTOR_0004).

registerDataSource returns a handle; call notifyChanged() whenever the data changes outside the inspector so connected views re-run, or hand the devframe a bridge to the source's own change signal via subscribe:

const handle = registerDataSource({
  id: 'my-plugin:state',
  title: 'My plugin state',
  data: () => store,
  writable: true, // opt-in: the inspector may mutate the live object
  subscribe: (notify) => { // optional: push the source's own change signal
    store.on('change', notify)
    return () => store.off('change', notify)
  },
})

handle.notifyChanged() // or notify imperatively

Mount

// the default export is the factory; call it for an instance:
import createDataInspectorDevframe from '@devframes/plugin-data-inspector'
// Vite
import { devframeVite } from '@devframes/vite/single'

devframeVite(createDataInspectorDevframe())

Standalone CLI

pnpx @devframes/plugin-data-inspector stats.json trace.jsonl # inspect local data files
pnpx @devframes/plugin-data-inspector build stats.json       # self-contained static export
pnpx @devframes/plugin-data-inspector attach                 # attach to a process running the inject entry

Static exports embed the dataset and run the same query engine client-side, so saved recipes stay portable.

Attach to another Node process

import { exposeDataInspector } from '@devframes/plugin-data-inspector/inject'

// pass sources inline, or register them separately beforehand
await exposeDataInspector({
  sources: [{ id: 'app:store', title: 'App store', data: () => store }],
})

or with zero code changes:

DEVFRAME_DATA_INSPECTOR=1 node --import @devframes/plugin-data-inspector/inject server.js

On the zero-code path there's nowhere to call registerDataSource, so the inject entry auto-registers a globalThis source: assign what you want to inspect onto the global object (globalThis.store = store) and query it live. Opt out with DEVFRAME_DATA_INSPECTOR_GLOBAL=0.

The inject entry binds 127.0.0.1, requires devframe's trust handshake with a per-run token by default, and advertises its endpoint in node_modules/.data-inspector/discovery.json, which pnpx @devframes/plugin-data-inspector attach picks up automatically.

[!WARNING] A connected inspector runs eval-grade jora queries against live objects: queries can invoke functions reachable as own properties and fire getters. Treat the inject endpoint like a debugger port: keep it on loopback and keep auth on.

Saved queries

Recipes ({ query, title?, description?, ...filters }) persist id-keyed in two scopes: workspace (committable, getStorageDir('workspace')/data-inspector/queries.json, shared with the team) and project (per-checkout, under node_modules).