Skip to content

Repository files navigation

bQuery DevTools

CI License

A browser DevTools extension for inspecting bQuery applications: the component tree, live signal and store values, and the reactive timeline — with time travel over recorded events.

It speaks the stable bridge protocol (v1) exported by @bquery/bquery/devtools, and nothing else. The framework and the extension ship on separate release cadences; the protocol is the contract between them.

Quick start

  1. Enable the bridge in the app you want to inspect:

    import { connectDevtoolsBridge, enableDevtools } from '@bquery/bquery/devtools';
    
    enableDevtools(true);
    connectDevtoolsBridge(); // exposes protocol v1 over window.postMessage

    Requires @bquery/bquery ≥ 1.15.0.

  2. Install the extension (see Installing).

  3. Open DevTools on that page and select the bQuery panel.

Features

  • Component tree — every custom element on the page, with its attributes, filterable by tag or attribute. Clicking a node reveals the real element in the Elements panel.
  • Signals & stores — live values with drill-down into nested objects and arrays, plus subscriber counts.
  • Timeline — reactive events as they happen, with a configurable ring buffer, per-type filter chips, free-text search, pause and clear.
  • Time travel — scrub back through recorded events and see the signal and store state as of that moment, reconstructed from the connect-time snapshot.
  • Capability negotiation — the panel only offers what the page's init handshake advertises, and says so when something is missing.
  • No host permissions by default — see Permissions.

Installing

From source

bun install
bun run deploy-v3   # Chromium / Edge (MV3) → dist/
bun run deploy-v2   # Firefox (MV2)         → dist/

Chromium / Edge: open chrome://extensions, enable Developer mode, click Load unpacked and pick dist/.

Firefox: run bun run deploy-v2, then open about:debuggingThis FirefoxLoad Temporary Add-on and pick dist/manifest.json.

bun run package writes a store-ready zip to artifacts/.

Permissions

The extension declares no host permissions. By default the panel talks to the page through chrome.devtools.inspectedWindow.eval, which a DevTools panel may use on the page it is inspecting without any site access, and drains buffered bridge messages on a short poll.

Enable live streaming in the panel's status bar upgrades that to a push transport: the panel asks for permission for the current site only, injects a small content-script relay, and events arrive as they happen. The permission is per-site, requested on a click, and revocable from the browser's extension settings. Everything works without it — you just get polling instead of push.

Permission Why
storage Panel preferences (buffer size, poll interval). No site access.
scripting Injecting the relay when you opt into live streaming.
optional_host_permissions Requested at runtime, one origin at a time.

Security model

The inspected page is treated as untrusted, because it is:

  • every message from the page is schema-validated before use, and messages from a foreign protocol version are rejected outright;
  • every value the panel displays is written through text sinks — the panel never assigns page-derived strings to innerHTML;
  • the panel's CSP forbids inline script and inline style;
  • panel → page messages are embedded as JSON data in the evaluated expression, never spliced into its source;
  • the background router forwards a panel's messages only to the tab that panel attached to, and only when they carry the session token it issued.

Development

bun install
bun run dev          # rebuild on change
bun run validate     # type-check + lint + unit tests
bun run test         # unit tests (bun test)
bun run test:e2e     # build, then Playwright smoke tests
bun run verify       # sanity-check a built dist/

See CONTRIBUTING.md for the full workflow and docs/ARCHITECTURE.md for how the pieces fit together. Publishing is documented in docs/PUBLISHING.md.

Protocol (v1)

Every message carries source: 'bquery-devtools' and the protocol version v.

Direction kind Purpose
panel → page hello Announce the panel; the page replies init
panel → page request { id, method, params }
page → panel init { capabilities } handshake
page → panel response { id, result | error }
page → panel event One streamed timeline entry

Methods: ping, getSnapshot, getTimeline ({ limit }), getComponentTree. Apps can add their own through connectDevtoolsBridge({ methods }); the panel ignores methods it does not know about.

Capabilities: signals, stores, components, timeline, time-travel.

Partial bQuery apps

The panel does not require a complete framework on the other end. Capabilities advertised in the handshake are treated as a hint; each section is graded on what the page actually answers, and they are fetched independently:

  • an app that loaded reactive but not store shows its signals, and the stores view says the page does not report any — not "0 stores";
  • a bridge implementing only getTimeline still gets a working timeline;
  • a bridge that advertises nothing is probed once, and lights up if it answers;
  • with no getComponentTree, the components view falls back to the flat registry the snapshot carries;
  • a page speaking a newer protocol version is named as incompatible instead of leaving the panel waiting.

A section the page refuses is asked for exactly once per connection. Refresh all re-probes everything, so enabling devtools or mounting your first component and pressing it is enough — no need to reopen DevTools.

See docs/ARCHITECTURE.md for the full degradation model.

Credits

Bootstrapped from BrowserExtensionTemplate by Jonas Pfalzgraf. Licensed under the MIT License.

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages