Skip to content

Devtools & Tracing

HyperDB can record a trace of every selector run and mutation, and ships an in-app devtool to browse them. Tracing is what powers the devtool, but you can also configure it independently.

The HyperDB devtool showing a trace list on the left and the Call Tree of a selector on the right

The devtool is exported from @will-be-done/hyperdb-devtool/react. Render HyperDBDevtools anywhere in your tree; it can read the database from DBProvider context, or take an explicit db prop.

import { DBProvider } from "@will-be-done/hyperdb/react";
import { HyperDBDevtools } from "@will-be-done/hyperdb-devtool/react";
import { db } from "./db";
export function App() {
return (
<DBProvider value={db}>
<YourApp />
<HyperDBDevtools db={db} initialIsOpen={false} />
</DBProvider>
);
}
PropDescription
dbThe SubscribableDB to inspect (defaults to context)
initialIsOpenWhether the panel starts open (persisted in localStorage)
position"top" | "bottom" | "left" | "right"
buttonPositionCorner for the toggle button
maxTracesMaximum number of traces to retain
theme"dark" | "light" | "system"

There is also HyperDBDevtoolsPanel for embedding the panel directly (without the floating toggle), with an embedded flag and an onClose callback.

Each selector and action run produces a root trace containing the nested selector frames, the index ranges scanned, and the mutations performed. Cache hits are recorded too, so you can see when a selector was reused instead of recomputed.

Set a tracer when constructing a DB. Pass the shared store, the string "default", or "disabled".

import { DB, hyperDBTraceStore } from "@will-be-done/hyperdb";
const db = new DB(driver, { tracer: hyperDBTraceStore });

To enable tracing for all databases that don’t specify their own, set the global default:

import {
setDefaultHyperDBTracer,
hyperDBTraceStore,
} from "@will-be-done/hyperdb/tracing";
setDefaultHyperDBTracer(hyperDBTraceStore);

Selector and action factories accept a trace option ({ enabled, startOn }):

import { createSelector } from "@will-be-done/hyperdb";
const selector = createSelector({
trace: { enabled: true, startOn: "devtoolOpen" },
});
FieldValuesMeaning
enabledboolean (default true)Whether this factory’s commands are traced
startOn"devtoolOpen" (default) | "load"When to begin collecting traces

startOn: "devtoolOpen" keeps overhead near zero until you actually open the devtool; "load" traces from startup.

Individual selectors and actions can opt out with skipTrace:

selector({
name: "hotPathSelector",
args: {},
skipTrace: true, // or { rootTrace: boolean, childTrace: boolean }
handler: function* () {
/* ... */
},
});

Use skipTrace on extremely hot paths where even tracing metadata is measurable, or to keep noisy internal selectors out of the devtool.