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

@intenda/opus-ui-app-graph

v0.1.0

Published

Compiles the packaged Opus UI app.json into a connection graph of the JSON dashboard layer — trait composition and scoped-state wiring — with a CLI for composition, impact, orphan, and broken-reference queries.

Readme

app-graph

A connection graph for the JSON dashboard layer of this Opus UI app. It answers "how are these dashboards/traits wired together" without reading the source files by hand.

Why it's built on legoz/public/app.json

app.json is the packaged artifact the Opus UI packager produces from legoz/app + every ensemble. Two properties make it the ideal source:

  1. Trait paths are already resolved. A source ref like ./../tasks is rewritten to its canonical @l2_dashboards/home/tasks form. No path-resolution guesswork.
  2. It mirrors the file tree (dashboard → @ensemble → folder → index.json), so every node maps back to a real source file, and trait / scope / flows / scps survive.

What it extracts

  • Trait graph — file A composes file B (forward + reverse edges).
  • State wiring, keyed by scope.relId.key (relId omitted = scope owner):
    • writessetState/setMultiState (explicit target or, when absent, self) and a flow's to/toKey (or self).
    • reads — a flow's from/fromKey (or self), scp triggers (source/sourceList + key), and inline state accessors in any string (state.||scope.relId||.key, state.self.key, state.app.key).
    • "self" with no enclosing declared scope (a mounted fragment) is recorded under the self scope, since its real scope is determined where it's composed.
  • Health — orphans (never composed), dangling static refs (target missing), and dynamic refs (%prop%, ((accessor)), {theme..} — runtime-supplied, not broken).

Install & invoke

Published as @intenda/opus-ui-app-graph, exposing the opus-ui-app-graph bin:

npm i -D @intenda/opus-ui-app-graph      # or  file:../tools/app-graph  for local dev
npx opus-ui-app-graph build
npx opus-ui-app-graph tree home/index

Or run the source directly (no install), from anywhere in the workspace:

node tools/app-graph/cli.cjs build
node tools/app-graph/cli.cjs tree home/index

Path resolution

All paths resolve against the consuming project, with overrides:

| input | flag | env | default | | --- | --- | --- | --- | | app.json | --app <path> | OPUS_APP_JSON | cwd's opusPackagerConfig (public/app.json); auto-discovered from a child project if cwd has none | | out dir | --out <dir> | OPUS_APP_GRAPH_OUT | <project>/app-graph-out (next to app.json, regardless of cwd) |

So node tools/app-graph/cli.cjs build works from the repo root and from legoz/ — both resolve legoz/public/app.json and write legoz/app-graph-out/.

Build

node tools/app-graph/cli.cjs build       # or: npx opus-ui-app-graph build

Outputs <project>/app-graph-out/app-graph.json (machine) and REPORT.md (summary). Pure JSON/AST parse — no API cost, ~0.5s.

Automatic rebuild (wired into the dev loop)

legoz's start, start-test, start-from-workspace, and start-from-workspace-test scripts run appgraph:watch alongside the packager and Vite via concurrently. It uses nodemon --watch public/app.json so the graph recompiles on every packager rebuild. Requires a one-time npm i in legoz (declared there as a file: devDependency until published). Standalone: cd legoz && npm run appgraph:watch.

If app.json doesn't exist yet, build.cjs no-ops with a warning; nodemon picks it up once the packager writes it.

Query

node tools/app-graph/cli.cjs <command> [args]     # or: npx opus-ui-app-graph <command>

| command | answers | | --- | --- | | tree <id> [--depth N] | what this file composes via traits (recursive) | | who <id> [--deep] | who composes this file (direct, or all ancestors) — orphan / impact check | | node <id> | one-node summary: source, scopes, traits, writes, reads | | writers <scope.key> | files that write this scoped state key | | readers <scope.key> | files that read / subscribe to it | | orphans [prefix] | nodes never composed by anyone (dead-code candidates) | | dangling | static trait refs whose target is missing | | path <a> <b> | shortest trait path a → b | | find <substr> | node ids containing substr | | stats | totals |

Ids may be abbreviated — home/index resolves to @l2_dashboards/home/index; the CLI reports candidates when ambiguous.

Examples

node tools/app-graph/cli.cjs tree home/index --depth 2
node tools/app-graph/cli.cjs who home/pieArea            # -> orphan = safe to delete
node tools/app-graph/cli.cjs writers home.filter
node tools/app-graph/cli.cjs readers home.filter

Known limitations

  • Trait-prop-driven state keys aren't resolved. A card whose action key is %setGridFilterKey% shows home.%setGridFilterKey%, not home.gridFilterPubLog (the concrete value lives in the instance's traitPrps, which this graph does not yet inline). writers/readers are exact for literal scoped keys (e.g. home.filter).
  • Reads cover state.… accessors, flows, and triggers — not flow.…/variable.… accessors. Edges are trait composition + state wiring only; gateway actions and theme tokens are not modeled.
  • A self reference inside a mounted fragment (no declared scope in that file) is recorded under the self scope rather than the scope it ends up in at runtime.
  • Generated from packaged output: a stale app.json yields a stale graph. The watcher keeps it current during npm run start*.