react-dev-panel 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +270 -68
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,130 +1,332 @@
1
1
  # react-dev-panel
2
2
 
3
- A **framework-agnostic, self-contained** floating dev panel for any React appno MUI, no
4
- Redux, no design-system coupling. One component, gated to internal/dev users, giving you:
3
+ A floating, in-app **developer panel for any React project**drop in one component and get a
4
+ draggable launcher with three tools:
5
5
 
6
- - **Developer Logs** — live console + network capture
7
- - **Page Performance** Core Web Vitals with fix hints
8
- - **Component Graph Inspector** — hover-to-source, component tree, "what's on this page", open-in-editor
6
+ - 🐛 **Developer Logs** — live console + network capture (status, duration, GraphQL op name/type,
7
+ request/response bodies & headers), with source/level filters, search, "this page" scoping, and
8
+ expandable entries.
9
+ - 📊 **Page Performance** — Core Web Vitals (LCP, INP, CLS, FCP, TTFB) with ratings and fix hints.
10
+ - 🧩 **Component Graph Inspector** — hover any element to identify its component, lock it, browse
11
+ the **parent → renders → imports** tree, see **what's mounted on the current page**, and **open
12
+ the source file in your editor**.
9
13
 
10
- Styles are injected once under a `.rdp-root` scope, so the panel can't clash with or be
11
- clashed by your app's theme. The only runtime requirement is React 18+.
14
+ Built on **MUI** (peer dependency) so it inherits your app's theme. Gating is a prop you control —
15
+ nothing renders in production unless you say so.
16
+
17
+ ---
18
+
19
+ ## Table of contents
20
+
21
+ - [Requirements](#requirements)
22
+ - [Install](#install)
23
+ - [Quick start](#quick-start)
24
+ - [Configuration](#configuration)
25
+ - [Tools](#tools)
26
+ - [Component Graph Inspector setup](#component-graph-inspector-setup)
27
+ - [1. Generate the graph](#1-generate-the-graph)
28
+ - [2. Serve it (pick an adapter)](#2-serve-it-pick-an-adapter)
29
+ - [3. Wire the client](#3-wire-the-client)
30
+ - [Open-in-editor](#open-in-editor)
31
+ - [Gating & security](#gating--security)
32
+ - [Custom tools](#custom-tools)
33
+ - [Theming](#theming)
34
+ - [CLI reference](#cli-reference)
35
+ - [API reference](#api-reference)
36
+ - [Troubleshooting](#troubleshooting)
37
+
38
+ ---
39
+
40
+ ## Requirements
41
+
42
+ `react-dev-panel` renders inside your app's existing MUI `ThemeProvider`, so these are **peer
43
+ dependencies** you already have in an MUI app:
44
+
45
+ | Peer | Version |
46
+ | --- | --- |
47
+ | `react` / `react-dom` | `>=18` |
48
+ | `@mui/material` | `>=7` |
49
+ | `@emotion/react`, `@emotion/styled` | `>=11` |
50
+ | `react-icons` | `>=5` |
51
+ | `typescript` *(optional)* | `>=5` — only the graph-generator CLI uses it |
52
+
53
+ > Not using MUI? This package won't render correctly without an MUI theme in context. (A
54
+ > style-agnostic build is out of scope for now.)
12
55
 
13
56
  ## Install
14
57
 
15
58
  ```bash
16
59
  npm i -D react-dev-panel
60
+ # or: pnpm add -D react-dev-panel / yarn add -D react-dev-panel
17
61
  ```
18
62
 
19
- ## Usage
63
+ ## Quick start
20
64
 
21
- Mount it once near your app root. It renders nothing in production by default.
65
+ Mount `<DevPanel/>` **once**, near your app root, **inside your MUI `ThemeProvider`**. It renders
66
+ nothing in production by default.
22
67
 
23
68
  ```tsx
24
69
  import { DevPanel } from 'react-dev-panel';
25
70
 
26
71
  export function Providers({ children }) {
27
72
  return (
28
- <>
73
+ <ThemeProvider theme={theme}>
29
74
  {children}
30
- <DevPanel
31
- // Gate: who may see it. Defaults to NODE_ENV !== 'production'.
32
- enabled={process.env.NODE_ENV !== 'production' || user?.isInternal}
33
- // Current route, for tools that display it (optional).
34
- getRoute={() => location.pathname}
35
- />
36
- </>
75
+ <DevPanel enabled={process.env.NODE_ENV !== 'production'} />
76
+ </ThemeProvider>
37
77
  );
38
78
  }
39
79
  ```
40
80
 
41
- That's it a draggable launcher appears in the corner.
81
+ A draggable wrench launcher appears in a corner. Open it → **Developer Logs** and **Page
82
+ Performance** work immediately with zero further setup.
83
+
84
+ The **Component Graph Inspector** needs a generated graph + a way to open files — see
85
+ [its setup section](#component-graph-inspector-setup). Until then, its hover/lock still identifies
86
+ components by name (from the React fiber tree); file paths and relationships light up once the
87
+ graph is served.
42
88
 
43
- ### Configuration
89
+ ## Configuration
90
+
91
+ `<DevPanel/>` takes a flat config object:
44
92
 
45
93
  | Prop | Type | Default | Purpose |
46
- |------|------|---------|---------|
47
- | `enabled` | `boolean` | `NODE_ENV !== 'production'` | Master gate the host owns the access decision. |
48
- | `getRoute` | `() => string` | `location.pathname` | Current route for display. Adapters wire your router. |
49
- | `openInEditor` | `(loc, editor?) => void` | protocol URL + copy | How source files open. Adapters provide a server-backed opener. |
50
- | `graphEndpoint` | `string` | — | URL serving the component graph JSON (Component Graph Inspector). |
51
- | `editor` | `'auto' \| 'vscode' \| 'cursor' \| 'webstorm' \| 'zed'` | `'auto'` | Preferred editor for protocol opens. |
52
- | `theme` | `{ accent?, accentContrast? }` | purple | Accent color override. |
53
- | `tools` | `string[]` | all | Restrict/reorder tools by id (`'logs'`, `'perf'`, `'graph'`). |
94
+ | --- | --- | --- | --- |
95
+ | `enabled` | `boolean` | `process.env.NODE_ENV !== 'production'` | Master gate. **You** own the access decision (env, internal-user role, flag). |
96
+ | `getRoute` | `() => string \| undefined` | `location.pathname` | Current route, for the "this page" / route displays. Wire your router (see per-framework notes). |
97
+ | `openInEditor` | `(loc, editor?) => void \| Promise<void \| boolean>` | protocol URL + copy | How source files open. Use `serverOpenInEditor` with an adapter for the best result. |
98
+ | `graphEndpoint` | `string` | — | URL serving the component-graph JSON. Use `DEFAULT_GRAPH_ENDPOINT` with an adapter. |
99
+ | `editor` | `'auto' \| 'vscode' \| 'cursor' \| 'webstorm' \| 'zed'` | `'auto'` | Preferred editor. `auto` lets the server detect the editor running the project. |
100
+ | `theme` | `{ accent?: string; accentContrast?: string }` | | Minor accent overrides (most styling comes from your MUI theme). |
101
+ | `tools` | `string[]` | all | Restrict/reorder tools by id: `'logs'`, `'perf'`, `'graph'`. |
54
102
 
55
- ### Custom tools
103
+ Example, fully wired (Next.js):
56
104
 
57
105
  ```tsx
58
- import { registerTool } from 'react-dev-panel';
106
+ 'use client';
107
+ import { usePathname } from 'next/navigation';
108
+ import { DevPanel, serverOpenInEditor, DEFAULT_GRAPH_ENDPOINT } from 'react-dev-panel';
59
109
 
60
- registerTool({
61
- id: 'my-tool',
62
- title: 'My Tool',
63
- subtitle: 'Does a thing',
64
- icon: <MyIcon />,
65
- Panel: ({ onClose }) => <div>…</div>,
66
- });
110
+ export function DevPanelMount() {
111
+ const pathname = usePathname();
112
+ return (
113
+ <DevPanel
114
+ enabled={process.env.NODE_ENV !== 'production'}
115
+ getRoute={() => pathname ?? undefined}
116
+ graphEndpoint={DEFAULT_GRAPH_ENDPOINT}
117
+ openInEditor={serverOpenInEditor}
118
+ tools={['graph', 'logs', 'perf']}
119
+ />
120
+ );
121
+ }
67
122
  ```
68
123
 
69
- ## Component Graph Inspector
124
+ ## Tools
70
125
 
71
- Reliable component inspection that works in normal dev (Turbopack/Vite — no special build):
126
+ | Tool | id | Setup | Notes |
127
+ | --- | --- | --- | --- |
128
+ | Developer Logs | `logs` | none | Patches `console` + `fetch`/XHR on first mount. Persists to `sessionStorage` (per tab). |
129
+ | Page Performance | `perf` | none | Uses `web-vitals`. INP needs an interaction before it reports. |
130
+ | Component Graph Inspector | `graph` | graph + endpoint | See below. Degrades gracefully without them. |
72
131
 
73
- 1. **Generate the graph** (components, files, parent/child/import/route edges):
74
- ```bash
75
- npx dev-panel-graph --scan src
76
- # → .dev-panel/component-graph.json
77
- ```
78
- 2. **Serve it + enable open-in-editor** with an adapter (below).
79
- 3. Open the panel → **Inspect mode** → hover (highlight + tooltip), click to lock, ⌘/Ctrl+click
80
- to open. Tabs: **Graph** (search + relationship tree), **Page** (what's mounted on this
81
- route), **File** (source + open).
132
+ ## Component Graph Inspector setup
82
133
 
83
- Resolution climbs the React fiber tree to the nearest component that's in the graph, so hovering
84
- a leaf still lands on your real app component. Open-in-editor uses the editor **running the
85
- project** (`launch-editor`) — VS Code, Cursor, WebStorm, Zed, … — via the adapter endpoint.
134
+ Three steps: **generate** the graph, **serve** it, **wire** the client.
86
135
 
87
- ### Adapters
136
+ ### 1. Generate the graph
137
+
138
+ A CLI scans your source with the TypeScript compiler and writes a JSON graph (components, files,
139
+ lines, and `renders` / `imports` / `route` edges):
140
+
141
+ ```bash
142
+ npx dev-panel-graph --scan src
143
+ # → .dev-panel/component-graph.json
144
+ ```
145
+
146
+ Re-run it after adding/moving components. Common options:
147
+
148
+ ```bash
149
+ npx dev-panel-graph --scan src,packages/ui/src --out .dev-panel/graph.json --root .
150
+ ```
151
+
152
+ Add it to your scripts so it's easy to refresh:
153
+
154
+ ```jsonc
155
+ // package.json
156
+ "scripts": {
157
+ "gen:dev-panel": "dev-panel-graph --scan src"
158
+ }
159
+ ```
160
+
161
+ Gitignore the output:
162
+
163
+ ```gitignore
164
+ .dev-panel/
165
+ ```
166
+
167
+ ### 2. Serve it (pick an adapter)
168
+
169
+ The graph JSON lives outside `public/`, so a tiny dev endpoint serves it (and opens files). Pick
170
+ the adapter for your stack — all three mount the same two endpoints
171
+ (`/dev-panel/graph`, `/dev-panel/open-file`).
172
+
173
+ **Vite** — one line; also regenerates the graph on dev start:
88
174
 
89
- **Vite**
90
175
  ```ts
176
+ // vite.config.ts
91
177
  import { devPanel } from 'react-dev-panel/vite';
92
- export default defineConfig({ plugins: [react(), devPanel({ scan: ['src'] })] });
178
+
179
+ export default defineConfig({
180
+ plugins: [react(), devPanel({ scan: ['src'] })],
181
+ });
93
182
  ```
94
183
 
95
- **Next.js (App Router)** — gate these yourself; dev/internal only.
184
+ **Next.js (App Router)** — add two route files (gate them yourself; dev/internal only):
185
+
96
186
  ```ts
97
187
  // app/dev-panel/graph/route.ts
98
- export const { GET } = createGraphRoute({ enabled: () => process.env.NODE_ENV !== 'production' });
188
+ import { createGraphRoute } from 'react-dev-panel/next';
189
+ export const dynamic = 'force-dynamic';
190
+ export const { GET } = createGraphRoute({
191
+ enabled: () => process.env.NODE_ENV !== 'production',
192
+ });
193
+ ```
194
+
195
+ ```ts
99
196
  // app/dev-panel/open-file/route.ts
100
- export const { POST } = createOpenFileRoute({ enabled: () => process.env.NODE_ENV !== 'production' });
197
+ import { createOpenFileRoute } from 'react-dev-panel/next';
198
+ export const dynamic = 'force-dynamic';
199
+ export const { POST } = createOpenFileRoute({
200
+ enabled: () => process.env.NODE_ENV !== 'production',
201
+ });
101
202
  ```
102
203
 
103
- **Any Node server (CRA/Express/custom)**
204
+ > In a monorepo where `cwd` differs from the repo root, pass `root` / `graphFile`:
205
+ > `createGraphRoute({ root: path.resolve(process.cwd(), '../..'), graphFile: 'apps/web/.dev-panel/component-graph.json' })`.
206
+
207
+ **Any Node server (CRA proxy / Express / custom)** — connect-style middleware:
208
+
104
209
  ```ts
105
210
  import { createDevPanelMiddleware } from 'react-dev-panel/server';
106
211
  app.use(createDevPanelMiddleware());
107
212
  ```
108
213
 
109
- Then wire the client:
214
+ ### 3. Wire the client
215
+
216
+ Point `<DevPanel/>` at the served endpoint and the server-backed opener:
217
+
110
218
  ```tsx
111
219
  import { DevPanel, serverOpenInEditor, DEFAULT_GRAPH_ENDPOINT } from 'react-dev-panel';
220
+
112
221
  <DevPanel enabled={isDev} graphEndpoint={DEFAULT_GRAPH_ENDPOINT} openInEditor={serverOpenInEditor} />
113
222
  ```
114
223
 
115
- Without an adapter the inspector still works at runtime (component names, tree from the graph if
116
- served, page scan); open-in-editor falls back to `editor://` protocol URLs then copy.
224
+ That's it open the panel, enable **Inspect mode**, hover, click to lock, and use the **Graph**,
225
+ **Page**, and **File** tabs.
226
+
227
+ > **No adapter / fully client-only?** Omit `graphEndpoint`. Hover still names components and the
228
+ > Page scan still lists them; file paths/relationships require the served graph, and open-in-editor
229
+ > falls back to `editor://` protocol URLs (then copy).
230
+
231
+ ## Open-in-editor
232
+
233
+ The detail card has a primary **Open in editor** button plus a `force:` row (**VS Code / Cursor /
234
+ WebStorm**). Resolution order:
235
+
236
+ 1. **Server** (`openInEditor={serverOpenInEditor}` + an adapter) → posts to `/dev-panel/open-file`,
237
+ which runs [`launch-editor`](https://www.npmjs.com/package/launch-editor) and opens the editor
238
+ **running the project** (respects `$EDITOR`). Most reliable. The `force:` buttons map to
239
+ `code` / `cursor` / `webstorm` CLIs — those must be on your `PATH`.
240
+ 2. **Protocol** (default opener, no server) → `vscode://` / `cursor://` / `webstorm://` / `zed://`.
241
+ 3. **Copy** the path to the clipboard if both fail.
242
+
243
+ `⌘/Ctrl + click` on a hovered element opens it directly.
244
+
245
+ ## Gating & security
246
+
247
+ - `enabled` is the master switch and **defaults to non-production**. In production it renders
248
+ nothing unless you explicitly pass `enabled` truthy — gate that on an internal-user role/flag.
249
+ - The adapter endpoints accept an `enabled()` callback — **gate them too** (NODE_ENV and/or auth);
250
+ they 404 in production by default.
251
+ - Open-file requests are **confined to the repo root** (path-traversal guarded).
252
+ - The graph JSON is read from disk by the endpoint and is **not** placed under `public/`, so it's
253
+ never a statically served production asset. Keep `.dev-panel/` gitignored.
254
+ - Sensitive request headers (`authorization`, `cookie`, …) are **redacted** before logging, and
255
+ presigned URL signatures are collapsed.
256
+
257
+ ## Custom tools
258
+
259
+ Register your own tool before mounting `<DevPanel/>`:
260
+
261
+ ```tsx
262
+ import { registerTool } from 'react-dev-panel';
263
+ import { LuFlask } from 'react-icons/lu';
264
+
265
+ registerTool({
266
+ id: 'my-tool',
267
+ title: 'My Tool',
268
+ subtitle: 'Does a useful thing',
269
+ color: 'primary', // primary | info | warning | success | error
270
+ icon: <LuFlask size={19} />,
271
+ Panel: ({ onClose }) => <YourMuiPanel onClose={onClose} />,
272
+ // optional:
273
+ Overlay: MyAlwaysMountedOverlay, // self-gating layer
274
+ useBadge: () => ({ label: '3', tone: 'error' }), // menu-row badge
275
+ init: () => { /* one-time setup on mount */ },
276
+ });
277
+ ```
278
+
279
+ Restrict/reorder which tools show with the `tools` prop.
280
+
281
+ ## Theming
282
+
283
+ The panel uses your app's MUI theme — colors, radius, typography all follow it automatically.
284
+
285
+ - Tweak the launcher accent via `theme={{ accent: '#6950E8' }}`.
286
+ - The detail chips use MUI's `soft` Chip variant. If your theme registers `soft` (e.g. the
287
+ Minimals template) it renders tinted; otherwise it falls back to a plain chip. No action needed.
288
+
289
+ ## CLI reference
290
+
291
+ ```text
292
+ dev-panel-graph [--root <dir>] [--scan <dir,dir>] [--out <file>]
293
+
294
+ --root repo root (default: cwd) — file paths in the graph are relative to this
295
+ --scan comma-separated dirs to scan (default: src)
296
+ --out output JSON path (default: .dev-panel/component-graph.json)
297
+ ```
298
+
299
+ The Vite adapter runs this for you on dev-server start (`generateOnStart`, default `true`).
300
+
301
+ ## API reference
302
+
303
+ **`react-dev-panel`**
304
+ - `DevPanel(config)` — the mountable component.
305
+ - `registerTool(def)`, `getRegisteredTools()` — custom tools.
306
+ - `serverOpenInEditor`, `createServerOpenInEditor(endpoint?)` — client opener that POSTs to the
307
+ open-file endpoint.
308
+ - `defaultOpenInEditor` — protocol-URL + copy opener (used when none is provided).
309
+ - `useDevPanelConfig()` — read the resolved config inside a custom tool.
310
+ - `DEFAULT_GRAPH_ENDPOINT`, `DEFAULT_OPEN_ENDPOINT` — `'/dev-panel/graph'`, `'/dev-panel/open-file'`.
311
+ - Types: `DevPanelConfig`, `DevPanelTheme`, `ToolDefinition`, `ToolPanelProps`, `EditorType`,
312
+ `SourceLocation`, `OpenInEditor`, `ComponentGraph`, `ComponentGraphNode`, `ComponentGraphEdge`.
117
313
 
118
- ## Roadmap
314
+ **`react-dev-panel/next`** — `createGraphRoute(opts)`, `createOpenFileRoute(opts)` (+ the endpoint
315
+ constants and `serverOpenInEditor`).
316
+ **`react-dev-panel/vite`** — `devPanel(opts)` (default + named export).
317
+ **`react-dev-panel/server`** — `createDevPanelMiddleware(opts)`.
119
318
 
120
- - [x] Framework-agnostic core (provider, launcher, self-contained styles, tool registry)
121
- - [x] Developer Logs · Page Performance · Component Graph Inspector
122
- - [x] CLI `dev-panel-graph` (TypeScript Compiler API)
123
- - [x] Adapters: `/next`, `/vite`, `/server`
124
- - [ ] Demo apps + browser-tested screenshots
125
- - [ ] Optional Babel/SWC transform for exact element line:col
319
+ ## Troubleshooting
320
+
321
+ | Symptom | Fix |
322
+ | --- | --- |
323
+ | Launcher doesn't appear | Check `enabled` is truthy; ensure it's mounted inside your MUI `ThemeProvider`. |
324
+ | Panels look unstyled / wrong colors | It must render inside an MUI `ThemeProvider`. |
325
+ | Graph tab says "not generated" | Run `npx dev-panel-graph`, then click **Retry graph load** (or reload). Confirm the adapter is mounted and `graphEndpoint` matches. |
326
+ | Hover shows `MuiButtonBaseRoot` / a host tag | You hovered a low-level/MUI element. Hover a container, or use **Graph → search** / the **Page** tab to find your app components. The resolver climbs to the nearest component that's in the graph. |
327
+ | "Open in editor" copies instead of opening | With an adapter: ensure the editor CLI (`code`/`cursor`/`webstorm`) is on `PATH`, or set `$EDITOR` before starting dev. Without an adapter, it relies on the OS protocol handler. |
328
+ | Page tab empty after navigation | Click **Rescan** — heavy/async pages mount content after the auto-scan. |
126
329
 
127
330
  ## License
128
331
 
129
332
  MIT
130
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-dev-panel",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "A framework-agnostic, self-contained floating dev panel for React: Developer Logs, Page Performance, and a Component Graph Inspector (hover-to-source, component tree, open-in-editor).",
5
5
  "license": "MIT",
6
6
  "author": "Pavan Kumar Mistry",