A React inspector panel for the TypeWire ecosystem. One timeline for REST, GraphQL, gRPC and WebSocket traffic, a live query cache view, a runtime override editor, and a settings tab — dropped into your app as a single component.
It renders any bridge from
@tahanabavi/type-devtools-core, so adding a transport is
one more connect* call, not a change in here.
pnpm add @tahanabavi/type-devtools @tahanabavi/type-devtools-coreWhat's in it
Timeline. One row per call, tagged by the wire it travelled on, newest
first. Filter by wire and status (pending / success / error), search across
labels, payloads, error kinds and transports, and pause to freeze the
stream while you read. Select a row for the full input / output / error.
Since typefetch grew a transport registry, one client speaks REST, GraphQL and
gRPC — so the badge shows http / graphql / grpc / ws, and the wire filter
is built from the traffic that actually arrived. An app that speaks one wire
never sees a filter it can't use; an app that registers a transport of its own
gets a badge for it without a change in here.
Normalized failures. A failed row shows typefetch's ErrorKind beside its
status, so 404, gRPC code 5 and GraphQL extensions.code: "NOT_FOUND" all
read as not_found. That is the field to scan on a mixed timeline: gRPC and
GraphQL carry no HTTP status, so without it a row could only say "error".
Live transfers. A call reporting upload or download progress draws a bar
under its row and an ↑ 62% · 1.2 MB / 2.0 MB readout in the detail. Chunked
responses report no total, so those get a moving indeterminate bar rather than
one stuck at zero. Progress is stored latest-only, outside the event log — a
single large upload would otherwise evict a whole session's history.
Override editor. The override engine was always wired through the bridge and both connectors — now it's buttons. From a selected row: force an error, add +1s / +2s latency, supply a mock response (paste JSON), or drop a WS frame. Active overrides show in a strip with per-item and bulk removal. Every future call of that endpoint/event is steered — no code, no contract change.
Cache. Every cached query with its state (fresh / stale / fetching /
error), plus one-click refetch, invalidate, and remove, and a
recent-mutations list. Driven entirely by the query client's event bus.
JSON tree. Collapsible and syntax-colored, with per-node copy and
search-match highlighting. Error, Map, Set, Date and BigInt are
normalized; cycles render as [Circular] instead of throwing.
Copy / export. Copy any entry as JSON, a REST entry as cURL, or
export the whole timeline to a .json file. cURL is offered for REST only: on
GraphQL the operation is query and the target is a root field, so the command
would not run — rebuilding the real POST means rebuilding the document and the
envelope, which belongs to the adapter, not the panel.
Settings (persisted to sessionStorage for the session):
Theme —
dark/light/auto(follows the host'sprefers-color-scheme).Density —
comfortable/compact.Animations — row-enter and a pending pulse, always gated by
prefers-reduced-motion.Sound — a soft blip on new traffic, a buzz on error. Off by default, synthesized with the Web Audio API so no audio asset ships.