@flotrace/runtime 2.0.2 → 2.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.
- package/README.md +86 -278
- package/dist/index.js +97 -1
- package/dist/index.mjs +99 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,24 +1,31 @@
|
|
|
1
1
|
# @flotrace/runtime
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Stop guessing why your React app re-renders.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
FloTrace is a desktop app that shows you, live, what your React tree is doing — every render, every prop change, every state mutation, every cascade — without leaving your editor and without uploading your source code anywhere.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
This package is the runtime that wires your app into the desktop. Drop it in once and you get:
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
- **A live component tree graph** — not a flat fiber list. See parent/child structure as it changes in real time.
|
|
10
|
+
- **Render reasons that actually answer "why?"** — props/state/context diffs, render frequency coloring, render-cascade tracing across files.
|
|
11
|
+
- **All your state in one panel** — Zustand, Redux, TanStack Query, Context, Router. No four browser extensions, no console.log.
|
|
12
|
+
- **Hooks + effects, classified and diffed** — 14 hook types, effect dep diffing, "did this effect re-run because X changed."
|
|
13
|
+
- **Network → state correlation** — every fetch/XHR mapped to the store update it caused.
|
|
14
|
+
- **Copy-as-Prompt** — turn any panel into an AI-ready prompt for Cursor/Claude/ChatGPT in one click.
|
|
15
|
+
|
|
16
|
+
Source code never leaves your machine. The runtime sends only metadata over `ws://localhost:3457` to the desktop app.
|
|
16
17
|
|
|
17
|
-
**
|
|
18
|
+
> **Using React Native?** Install [`@flotrace/runtime-native`](https://www.npmjs.com/package/@flotrace/runtime-native) instead. This package patches `fetch`/`XMLHttpRequest` in ways that crash the RN bridge.
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
[**Download the desktop app →**](https://flotrace.dev/download) · [Docs](https://flotrace.dev/docs) · [Compare to React DevTools](https://flotrace.dev/compare/react-devtools)
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 30-second setup
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -D @flotrace/runtime
|
|
28
|
+
```
|
|
22
29
|
|
|
23
30
|
```tsx
|
|
24
31
|
import { FloTraceProvider } from '@flotrace/runtime';
|
|
@@ -32,75 +39,29 @@ createRoot(document.getElementById('root')!).render(
|
|
|
32
39
|
);
|
|
33
40
|
```
|
|
34
41
|
|
|
35
|
-
|
|
42
|
+
Launch the FloTrace desktop app. Reload your dev server. Done — your tree appears.
|
|
36
43
|
|
|
37
|
-
|
|
44
|
+
**Peer dependencies:** React >= 16.9.0 (uses `<Profiler>` API). Auto-disables in production via `process.env.NODE_ENV`.
|
|
38
45
|
|
|
39
|
-
|
|
46
|
+
---
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
<FloTraceProvider config={{ port: 3457, appName: 'My App' }}>
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
| Option | Type | Default | Description |
|
|
46
|
-
|--------|------|---------|-------------|
|
|
47
|
-
| `port` | `number` | `3457` | WebSocket server port |
|
|
48
|
-
| `appName` | `string` | `'React App'` | App name displayed in FloTrace |
|
|
49
|
-
| `enabled` | `boolean` | `true` in dev | Enable/disable tracking |
|
|
50
|
-
| `autoReconnect` | `boolean` | `true` | Auto-reconnect on disconnect |
|
|
51
|
-
| `reconnectInterval` | `number` | `2000` | Reconnect interval (ms) |
|
|
52
|
-
| `trackAllRenders` | `boolean` | `true` | Track all component renders |
|
|
53
|
-
| `includeProps` | `boolean` | `true` | Include props in render events |
|
|
54
|
-
| `trackZustand` | `boolean` | `true` | Enable Zustand state tracking |
|
|
55
|
-
| `trackRedux` | `boolean` | `true` | Enable Redux state tracking |
|
|
56
|
-
| `trackRouter` | `boolean` | `true` | Enable URL navigation tracking |
|
|
57
|
-
| `trackContext` | `boolean` | `true` | Enable React Context tracking |
|
|
58
|
-
| `trackTanstackQuery` | `boolean` | `true` | Enable TanStack Query tracking |
|
|
59
|
-
|
|
60
|
-
## Framework Setup
|
|
61
|
-
|
|
62
|
-
### Vite + React
|
|
63
|
-
|
|
64
|
-
```tsx
|
|
65
|
-
// src/main.tsx
|
|
66
|
-
import { FloTraceProvider } from '@flotrace/runtime';
|
|
67
|
-
import { createRoot } from 'react-dom/client';
|
|
68
|
-
import App from './App';
|
|
69
|
-
|
|
70
|
-
createRoot(document.getElementById('root')!).render(
|
|
71
|
-
<FloTraceProvider config={{ appName: 'My Vite App' }}>
|
|
72
|
-
<App />
|
|
73
|
-
</FloTraceProvider>
|
|
74
|
-
);
|
|
75
|
-
```
|
|
48
|
+
## Framework recipes
|
|
76
49
|
|
|
77
50
|
### Next.js (App Router)
|
|
78
51
|
|
|
79
52
|
```tsx
|
|
80
53
|
// app/providers.tsx
|
|
81
54
|
'use client';
|
|
82
|
-
|
|
83
55
|
import { FloTraceProvider } from '@flotrace/runtime';
|
|
84
56
|
|
|
85
57
|
export function Providers({ children }: { children: React.ReactNode }) {
|
|
86
|
-
return
|
|
87
|
-
<FloTraceProvider config={{ appName: 'My Next.js App' }}>
|
|
88
|
-
{children}
|
|
89
|
-
</FloTraceProvider>
|
|
90
|
-
);
|
|
58
|
+
return <FloTraceProvider config={{ appName: 'My Next.js App' }}>{children}</FloTraceProvider>;
|
|
91
59
|
}
|
|
92
60
|
|
|
93
61
|
// app/layout.tsx
|
|
94
62
|
import { Providers } from './providers';
|
|
95
|
-
|
|
96
63
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
97
|
-
return
|
|
98
|
-
<html>
|
|
99
|
-
<body>
|
|
100
|
-
<Providers>{children}</Providers>
|
|
101
|
-
</body>
|
|
102
|
-
</html>
|
|
103
|
-
);
|
|
64
|
+
return <html><body><Providers>{children}</Providers></body></html>;
|
|
104
65
|
}
|
|
105
66
|
```
|
|
106
67
|
|
|
@@ -120,272 +81,119 @@ export default function App({ Component, pageProps }: AppProps) {
|
|
|
120
81
|
}
|
|
121
82
|
```
|
|
122
83
|
|
|
123
|
-
### Create React App
|
|
124
|
-
|
|
125
|
-
```tsx
|
|
126
|
-
// src/index.tsx
|
|
127
|
-
import { FloTraceProvider } from '@flotrace/runtime';
|
|
128
|
-
import { createRoot } from 'react-dom/client';
|
|
129
|
-
import App from './App';
|
|
84
|
+
### Vite / Create React App
|
|
130
85
|
|
|
131
|
-
|
|
132
|
-
<FloTraceProvider config={{ appName: 'My CRA App' }}>
|
|
133
|
-
<App />
|
|
134
|
-
</FloTraceProvider>
|
|
135
|
-
);
|
|
136
|
-
```
|
|
86
|
+
Same as the 30-second setup above — wrap `<App />` at the root.
|
|
137
87
|
|
|
138
|
-
|
|
88
|
+
---
|
|
139
89
|
|
|
140
|
-
|
|
90
|
+
## Wire up your state stores
|
|
141
91
|
|
|
142
|
-
Pass
|
|
92
|
+
State tracking is the killer feature. Pass your stores to the provider and they show up in the desktop's State panel with live diffs:
|
|
143
93
|
|
|
144
94
|
```tsx
|
|
145
95
|
import { FloTraceProvider } from '@flotrace/runtime';
|
|
146
|
-
import { useBearStore } from './
|
|
147
|
-
import {
|
|
96
|
+
import { useBearStore } from './zustandStore';
|
|
97
|
+
import { store as reduxStore } from './reduxStore';
|
|
98
|
+
import { queryClient } from './queryClient';
|
|
148
99
|
|
|
149
100
|
<FloTraceProvider
|
|
150
|
-
stores={{ bearStore: useBearStore, userStore: useUserStore }}
|
|
151
101
|
config={{ appName: 'My App' }}
|
|
102
|
+
stores={{ bearStore: useBearStore }} // Zustand — keys become store names
|
|
103
|
+
reduxStore={reduxStore} // Redux — pass your store directly
|
|
104
|
+
queryClient={queryClient} // TanStack Query — pass your client
|
|
152
105
|
>
|
|
153
106
|
<App />
|
|
154
107
|
</FloTraceProvider>
|
|
155
108
|
```
|
|
156
109
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
Pass your Redux store via the `reduxStore` prop:
|
|
160
|
-
|
|
161
|
-
```tsx
|
|
162
|
-
import { FloTraceProvider } from '@flotrace/runtime';
|
|
163
|
-
import { store } from './store';
|
|
110
|
+
Router tracking is automatic — it patches the History API and works with React Router, TanStack Router, Next.js, etc.
|
|
164
111
|
|
|
165
|
-
|
|
166
|
-
reduxStore={store}
|
|
167
|
-
config={{ appName: 'My App' }}
|
|
168
|
-
>
|
|
169
|
-
<App />
|
|
170
|
-
</FloTraceProvider>
|
|
171
|
-
```
|
|
112
|
+
---
|
|
172
113
|
|
|
173
|
-
|
|
114
|
+
## Configuration
|
|
174
115
|
|
|
175
|
-
|
|
116
|
+
All options optional. Sensible defaults for development.
|
|
176
117
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
118
|
+
| Option | Type | Default | Description |
|
|
119
|
+
|--------|------|---------|-------------|
|
|
120
|
+
| `appName` | `string` | `'React App'` | Shown in the FloTrace connection pill |
|
|
121
|
+
| `port` | `number` | `3457` | WebSocket server port |
|
|
122
|
+
| `enabled` | `boolean` | dev only | `false` to hard-disable |
|
|
123
|
+
| `autoReconnect` | `boolean` | `true` | Reconnect on disconnect |
|
|
124
|
+
| `reconnectInterval` | `number` | `2000` | Base reconnect delay (ms, exponential backoff) |
|
|
125
|
+
| `trackAllRenders` | `boolean` | `true` | Track every commit via `<Profiler>` |
|
|
126
|
+
| `includeProps` | `boolean` | `true` | Include prop values in render events |
|
|
127
|
+
| `trackZustand` / `trackRedux` / `trackRouter` / `trackContext` / `trackTanstackQuery` | `boolean` | `true` | Per-tracker toggles |
|
|
180
128
|
|
|
181
|
-
|
|
129
|
+
---
|
|
182
130
|
|
|
183
|
-
|
|
184
|
-
<FloTraceProvider
|
|
185
|
-
queryClient={queryClient}
|
|
186
|
-
config={{ appName: 'My App' }}
|
|
187
|
-
>
|
|
188
|
-
<App />
|
|
189
|
-
</FloTraceProvider>
|
|
190
|
-
</QueryClientProvider>
|
|
191
|
-
```
|
|
131
|
+
## Production safety
|
|
192
132
|
|
|
193
|
-
|
|
133
|
+
FloTrace is **disabled in production** by default (`enabled` defaults to `process.env.NODE_ENV === 'development'`). For belt-and-braces tree-shaking, dynamic-import in dev only:
|
|
194
134
|
|
|
195
135
|
```tsx
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
import { queryClient } from './queryClient';
|
|
200
|
-
|
|
201
|
-
<FloTraceProvider
|
|
202
|
-
config={{ appName: 'My App' }}
|
|
203
|
-
stores={{ bearStore: useBearStore }}
|
|
204
|
-
reduxStore={store}
|
|
205
|
-
queryClient={queryClient}
|
|
206
|
-
>
|
|
207
|
-
<App />
|
|
208
|
-
</FloTraceProvider>
|
|
136
|
+
const FloTraceProvider = process.env.NODE_ENV === 'development'
|
|
137
|
+
? (await import('@flotrace/runtime')).FloTraceProvider
|
|
138
|
+
: ({ children }: { children: React.ReactNode }) => <>{children}</>;
|
|
209
139
|
```
|
|
210
140
|
|
|
211
|
-
|
|
141
|
+
---
|
|
212
142
|
|
|
213
|
-
##
|
|
143
|
+
## Targeted profiling
|
|
214
144
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
Wrap specific components to track their renders and props individually:
|
|
145
|
+
For one-off component tracking without the full provider:
|
|
218
146
|
|
|
219
147
|
```tsx
|
|
220
|
-
import { withFloTrace } from '@flotrace/runtime';
|
|
221
|
-
|
|
222
|
-
const ProfiledComponent = withFloTrace(MyComponent, 'MyComponent');
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### `useTrackProps()` — Track prop changes
|
|
148
|
+
import { withFloTrace, useTrackProps } from '@flotrace/runtime';
|
|
226
149
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
```tsx
|
|
230
|
-
import { useTrackProps } from '@flotrace/runtime';
|
|
150
|
+
const Profiled = withFloTrace(MyComponent, 'MyComponent');
|
|
231
151
|
|
|
232
152
|
function MyComponent(props: MyProps) {
|
|
233
153
|
useTrackProps('MyComponent', props);
|
|
234
|
-
// ...
|
|
235
|
-
}
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
### `useFloTrace()` — Access runtime context
|
|
239
|
-
|
|
240
|
-
```tsx
|
|
241
|
-
import { useFloTrace } from '@flotrace/runtime';
|
|
242
|
-
|
|
243
|
-
function DebugInfo() {
|
|
244
|
-
const floTrace = useFloTrace();
|
|
245
|
-
return <div>Connected: {floTrace?.connected ? 'Yes' : 'No'}</div>;
|
|
154
|
+
// ...
|
|
246
155
|
}
|
|
247
156
|
```
|
|
248
157
|
|
|
249
|
-
|
|
158
|
+
---
|
|
250
159
|
|
|
251
|
-
|
|
160
|
+
## Privacy & security
|
|
252
161
|
|
|
253
|
-
|
|
162
|
+
- Source code never leaves your machine. The runtime sends only metadata (component names, prop types, render counts) over `ws://localhost:3457`.
|
|
163
|
+
- Desktop app binds to `127.0.0.1` only. LAN connections (physical devices) require an opt-in auth token.
|
|
164
|
+
- The desktop is closed-source commercial; this runtime package is **MIT-licensed** and open at [github.com/flotrace](https://github.com/flotrace).
|
|
254
165
|
|
|
255
|
-
|
|
256
|
-
// src/main.tsx
|
|
257
|
-
const FloTraceProvider = process.env.NODE_ENV === 'development'
|
|
258
|
-
? (await import('@flotrace/runtime')).FloTraceProvider
|
|
259
|
-
: ({ children }: { children: React.ReactNode }) => <>{children}</>;
|
|
260
|
-
```
|
|
166
|
+
---
|
|
261
167
|
|
|
262
168
|
## Troubleshooting
|
|
263
169
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
1. Ensure the FloTrace desktop app is running
|
|
267
|
-
2. Check the port matches (default: 3457)
|
|
268
|
-
3. Verify `config.enabled` is `true`
|
|
269
|
-
4. Check browser console for `[FloTrace]` logs
|
|
270
|
-
|
|
271
|
-
### Zustand stores not appearing
|
|
272
|
-
|
|
273
|
-
- Stores must be passed explicitly via the `stores` prop
|
|
274
|
-
- Each value must be a Zustand hook (function with `.getState()` and `.subscribe()` methods)
|
|
275
|
-
- Check console for `[FloTrace] Skipping "..." — not a valid Zustand store` warnings
|
|
276
|
-
|
|
277
|
-
### Component tree is missing or incomplete
|
|
170
|
+
**"Not connected"** — Is the desktop app running? Is `enabled: true`? Check browser console for `[FloTrace]` logs.
|
|
278
171
|
|
|
279
|
-
|
|
280
|
-
- React DevTools browser extension improves reliability
|
|
281
|
-
- Tree depth is capped at 100 levels, children at 300 per node
|
|
282
|
-
- Reload the page if the tree appears empty
|
|
172
|
+
**Zustand stores missing** — Stores must be passed via the `stores` prop, and each value must be a Zustand hook (has `.getState()` and `.subscribe()`).
|
|
283
173
|
|
|
284
|
-
|
|
174
|
+
**Tree empty or partial** — Reload the page. The walker uses React DevTools hook or DOM-based fiber access; depth is capped at 100, children at 300/node.
|
|
285
175
|
|
|
286
|
-
|
|
287
|
-
- After 10 failed attempts, reload the page or restart FloTrace to retry
|
|
288
|
-
- Check that no firewall or proxy is blocking `ws://localhost:3457`
|
|
176
|
+
**WebSocket reconnecting** — Exponential backoff (2s → 30s, 10 attempts). After that, reload the page or restart the desktop.
|
|
289
177
|
|
|
290
|
-
|
|
178
|
+
---
|
|
291
179
|
|
|
292
|
-
|
|
180
|
+
## API reference
|
|
293
181
|
|
|
294
|
-
|
|
295
|
-
|--------|-------------|
|
|
296
|
-
| `FloTraceProvider` | Main provider — wraps your app, manages WebSocket connection |
|
|
297
|
-
| `withFloTrace(Component, name?)` | HOC for targeted component profiling |
|
|
298
|
-
|
|
299
|
-
### Hooks
|
|
300
|
-
|
|
301
|
-
| Export | Description |
|
|
302
|
-
|--------|-------------|
|
|
303
|
-
| `useFloTrace()` | Access connection state and config |
|
|
304
|
-
| `useTrackProps(name, props)` | Track prop changes for a component |
|
|
305
|
-
|
|
306
|
-
### Types
|
|
307
|
-
|
|
308
|
-
| Export | Description |
|
|
309
|
-
|--------|-------------|
|
|
310
|
-
| `FloTraceConfig` | Configuration options interface |
|
|
311
|
-
| `FloTraceProviderProps` | Props for FloTraceProvider |
|
|
312
|
-
| `SerializedValue` | Serialized value type for safe WebSocket transmission |
|
|
313
|
-
| `LiveTreeNode` | Node in the live component tree |
|
|
314
|
-
| `ReduxStoreApi` | Minimal Redux store interface |
|
|
315
|
-
| `TanStackQueryClientApi` | Duck-typed TanStack Query client interface |
|
|
316
|
-
| `TrackingOptions` | Tracking options from extension |
|
|
317
|
-
| `DEFAULT_CONFIG` | Default configuration values |
|
|
318
|
-
| `DetailedRenderReason` | Detailed render reason with prop/state/context diffs |
|
|
319
|
-
| `HookType`, `HookInfo` | Hook type classification and inspection data |
|
|
320
|
-
| `EffectInfo` | Effect info with willRun and dep diffs |
|
|
321
|
-
| `TimelineEvent`, `TimelineEventType` | Component lifecycle events |
|
|
322
|
-
| `TanStackQueryInfo`, `TanStackMutationInfo` | Query and mutation tracking data |
|
|
323
|
-
| `NetworkRequestEntry` | Network request metadata (method, status, timing, correlation) |
|
|
324
|
-
| `Fiber`, `FiberHookState`, `FiberEffect` | React fiber type definitions |
|
|
325
|
-
|
|
326
|
-
### Advanced Exports
|
|
182
|
+
See [flotrace.dev/docs/runtime](https://flotrace.dev/docs/runtime) for the full export surface (40+ hooks, trackers, and types). Quick index:
|
|
327
183
|
|
|
328
184
|
| Export | Description |
|
|
329
|
-
|
|
330
|
-
| `
|
|
331
|
-
| `
|
|
332
|
-
| `
|
|
333
|
-
| `
|
|
334
|
-
| `
|
|
335
|
-
| `
|
|
336
|
-
| `getNodeHooks(nodeId)` | Inspect hooks for a specific component |
|
|
337
|
-
| `getNodeEffects(nodeId)` | Inspect effects for a specific component |
|
|
338
|
-
| `getDetailedRenderReason(nodeId)` | Get detailed render reason (prop/state/context diffs) |
|
|
339
|
-
| `getFiberRefMap()` | Get map of all tracked fiber refs |
|
|
340
|
-
| `inspectHooks(fiber)` | Classify and inspect hooks from fiber |
|
|
341
|
-
| `inspectEffects(fiber)` | Inspect effects from fiber updateQueue |
|
|
342
|
-
| `installZustandTracker()` / `uninstall...` | Zustand per-store subscription tracking |
|
|
343
|
-
| `installReduxTracker()` / `uninstall...` | Redux store subscription tracking |
|
|
344
|
-
| `installRouterTracker()` / `uninstall...` | History API patching for route tracking |
|
|
345
|
-
| `installTanStackQueryTracker()` / `uninstall...` | TanStack Query cache subscriber (duck-typed) |
|
|
346
|
-
| `installNetworkTracker()` / `uninstall...` | Fetch/XHR patching for network monitoring |
|
|
347
|
-
| `prewarmNetworkTracker()` | Pre-install patches to capture page-load requests |
|
|
348
|
-
| `installTimelineTracker()` / `uninstall...` | Component lifecycle event tracking |
|
|
349
|
-
| `recordTimelineEvent()` | Manually record a timeline event |
|
|
350
|
-
| `getTimeline(componentId)` | Get timeline events for a component |
|
|
351
|
-
| `serializeValue(value)` | Serialize a value for WebSocket |
|
|
352
|
-
| `serializeProps(props)` | Serialize props object |
|
|
353
|
-
| `isReduxStore(obj)` | Type guard for Redux store |
|
|
354
|
-
| `isTanStackQueryClient(obj)` | Type guard for TanStack Query client |
|
|
355
|
-
|
|
356
|
-
## Publishing
|
|
357
|
-
|
|
358
|
-
### Prerequisites
|
|
359
|
-
|
|
360
|
-
```bash
|
|
361
|
-
npm login
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
### Release Scripts
|
|
365
|
-
|
|
366
|
-
| Script | Version Change | When to Use |
|
|
367
|
-
|--------|---------------|-------------|
|
|
368
|
-
| `npm run release:patch` | `0.1.0` → `0.1.1` | Bug fixes, small tweaks |
|
|
369
|
-
| `npm run release:minor` | `0.1.0` → `0.2.0` | New features, non-breaking changes |
|
|
370
|
-
| `npm run release:major` | `0.1.0` → `1.0.0` | Breaking API changes |
|
|
371
|
-
|
|
372
|
-
Each release script automatically:
|
|
373
|
-
1. Bumps the version in `package.json`
|
|
374
|
-
2. Creates a git commit and tag (e.g. `v0.1.1`)
|
|
375
|
-
3. Cleans `dist/`, rebuilds, and typechecks (`prepublishOnly`)
|
|
376
|
-
4. Publishes to npm under `@flotrace` scope
|
|
377
|
-
|
|
378
|
-
### From the monorepo root
|
|
185
|
+
|---|---|
|
|
186
|
+
| `FloTraceProvider` | Main provider component |
|
|
187
|
+
| `withFloTrace(Component, name?)` | HOC for targeted profiling |
|
|
188
|
+
| `useFloTrace()` | Connection state + config |
|
|
189
|
+
| `useTrackProps(name, props)` | Track prop changes |
|
|
190
|
+
| `installXxxTracker()` / `uninstallXxxTracker()` | Manual tracker control (Zustand, Redux, Router, TanStack Query, Network, Timeline) |
|
|
191
|
+
| `getNodeHooks(nodeId)` / `getNodeEffects(nodeId)` / `getDetailedRenderReason(nodeId)` | Inspector accessors |
|
|
379
192
|
|
|
380
|
-
|
|
381
|
-
|--------|--------|
|
|
382
|
-
| `npm run runtime:release:patch` | Bump patch + build + publish (e.g. `0.1.0` → `0.1.1`) |
|
|
383
|
-
| `npm run runtime:release:minor` | Bump minor + build + publish (e.g. `0.1.0` → `0.2.0`) |
|
|
384
|
-
| `npm run runtime:release:major` | Bump major + build + publish (e.g. `0.1.0` → `1.0.0`) |
|
|
385
|
-
| `npm run runtime:publish` | Publish current version as-is (no version bump) |
|
|
193
|
+
Type exports: `FloTraceConfig`, `LiveTreeNode`, `SerializedValue`, `HookInfo`, `EffectInfo`, `TimelineEvent`, `NetworkRequestEntry`, `Fiber`, etc.
|
|
386
194
|
|
|
387
|
-
|
|
195
|
+
---
|
|
388
196
|
|
|
389
197
|
## License
|
|
390
198
|
|
|
391
|
-
MIT
|
|
199
|
+
MIT. Issues and PRs welcome at [github.com/flotrace](https://github.com/flotrace).
|
package/dist/index.js
CHANGED
|
@@ -47,6 +47,69 @@ __reExport(index_exports, require("@flotrace/runtime-core"), module.exports);
|
|
|
47
47
|
var import_react = __toESM(require("react"));
|
|
48
48
|
var import_runtime_core3 = require("@flotrace/runtime-core");
|
|
49
49
|
|
|
50
|
+
// package.json
|
|
51
|
+
var package_default = {
|
|
52
|
+
name: "@flotrace/runtime",
|
|
53
|
+
version: "2.2.2",
|
|
54
|
+
description: "Runtime package for FloTrace - enables real-time render tracking in your React app",
|
|
55
|
+
main: "./dist/index.js",
|
|
56
|
+
module: "./dist/index.mjs",
|
|
57
|
+
types: "./dist/index.d.ts",
|
|
58
|
+
exports: {
|
|
59
|
+
".": {
|
|
60
|
+
types: "./dist/index.d.ts",
|
|
61
|
+
import: "./dist/index.mjs",
|
|
62
|
+
require: "./dist/index.js"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
files: [
|
|
66
|
+
"dist"
|
|
67
|
+
],
|
|
68
|
+
scripts: {
|
|
69
|
+
build: "tsup",
|
|
70
|
+
dev: "tsup --watch",
|
|
71
|
+
typecheck: "tsc --noEmit",
|
|
72
|
+
clean: "rm -rf dist",
|
|
73
|
+
prepublishOnly: "npm run -w @flotrace/runtime-core build && npm run clean && npm run build && npm run typecheck",
|
|
74
|
+
"release:patch": "npm version patch && npm publish",
|
|
75
|
+
"release:minor": "npm version minor && npm publish",
|
|
76
|
+
"release:major": "npm version major && npm publish"
|
|
77
|
+
},
|
|
78
|
+
dependencies: {
|
|
79
|
+
"@flotrace/runtime-core": "2.2.2"
|
|
80
|
+
},
|
|
81
|
+
peerDependencies: {
|
|
82
|
+
react: ">=16.9.0",
|
|
83
|
+
"@types/react": ">=16.9.0"
|
|
84
|
+
},
|
|
85
|
+
peerDependenciesMeta: {
|
|
86
|
+
"@types/react": {
|
|
87
|
+
optional: true
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
devDependencies: {
|
|
91
|
+
tsup: "^8.0.0",
|
|
92
|
+
typescript: "^5.3.0"
|
|
93
|
+
},
|
|
94
|
+
keywords: [
|
|
95
|
+
"react",
|
|
96
|
+
"devtools",
|
|
97
|
+
"profiler",
|
|
98
|
+
"render",
|
|
99
|
+
"performance",
|
|
100
|
+
"flotrace"
|
|
101
|
+
],
|
|
102
|
+
license: "MIT",
|
|
103
|
+
repository: {
|
|
104
|
+
type: "git",
|
|
105
|
+
url: "https://github.com/flotrace/flotrace.git",
|
|
106
|
+
directory: "packages/runtime"
|
|
107
|
+
},
|
|
108
|
+
publishConfig: {
|
|
109
|
+
access: "public"
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
50
113
|
// src/routerTracker.ts
|
|
51
114
|
var isInstalled = false;
|
|
52
115
|
var debounceTimer = null;
|
|
@@ -571,6 +634,7 @@ function flushBuffer() {
|
|
|
571
634
|
|
|
572
635
|
// src/FloTraceProvider.tsx
|
|
573
636
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
637
|
+
var RUNTIME_VERSION = package_default.version;
|
|
574
638
|
var pendingCleanupTimer = null;
|
|
575
639
|
function safeTrackerOp(name, op) {
|
|
576
640
|
try {
|
|
@@ -616,7 +680,8 @@ function FloTraceProvider({ children, config = {}, stores, reduxStore, queryClie
|
|
|
616
680
|
appName: config.appName ?? deriveWebAppName(),
|
|
617
681
|
appId: config.appId ?? deriveWebAppId(),
|
|
618
682
|
frameworkName: config.frameworkName ?? framework.frameworkName,
|
|
619
|
-
frameworkVersion: config.frameworkVersion ?? framework.frameworkVersion
|
|
683
|
+
frameworkVersion: config.frameworkVersion ?? framework.frameworkVersion,
|
|
684
|
+
runtimeVersion: config.runtimeVersion ?? RUNTIME_VERSION
|
|
620
685
|
};
|
|
621
686
|
const [connected, setConnected] = import_react.default.useState(false);
|
|
622
687
|
const trackingOptionsRef = (0, import_react.useRef)({});
|
|
@@ -754,6 +819,37 @@ function FloTraceProvider({ children, config = {}, stores, reduxStore, queryClie
|
|
|
754
819
|
}
|
|
755
820
|
break;
|
|
756
821
|
}
|
|
822
|
+
// Value Lineage — resolve the origin chain for a prop or hook value.
|
|
823
|
+
case "ext:traceValue": {
|
|
824
|
+
try {
|
|
825
|
+
const trace = (0, import_runtime_core3.resolveValueTrace)({
|
|
826
|
+
nodeId: message.nodeId,
|
|
827
|
+
propPath: message.propPath,
|
|
828
|
+
hookPath: message.hookPath
|
|
829
|
+
});
|
|
830
|
+
client3.sendImmediate({
|
|
831
|
+
type: "runtime:valueTrace",
|
|
832
|
+
trace: { requestId: message.requestId, ...trace },
|
|
833
|
+
timestamp: Date.now()
|
|
834
|
+
});
|
|
835
|
+
} catch (error) {
|
|
836
|
+
console.error("[FloTrace] resolveValueTrace threw:", error);
|
|
837
|
+
client3.sendImmediate({
|
|
838
|
+
type: "runtime:valueTrace",
|
|
839
|
+
trace: {
|
|
840
|
+
requestId: message.requestId,
|
|
841
|
+
rootNodeId: message.nodeId,
|
|
842
|
+
rootPropPath: message.propPath,
|
|
843
|
+
rootHookPath: message.hookPath,
|
|
844
|
+
steps: [],
|
|
845
|
+
resolvedAtMs: Date.now(),
|
|
846
|
+
error: "value-not-found"
|
|
847
|
+
},
|
|
848
|
+
timestamp: Date.now()
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
break;
|
|
852
|
+
}
|
|
757
853
|
case "ext:startNetworkCapture":
|
|
758
854
|
safeTrackerOp("Network capture start", () => installNetworkTracker(client3));
|
|
759
855
|
break;
|
package/dist/index.mjs
CHANGED
|
@@ -26,9 +26,73 @@ import {
|
|
|
26
26
|
installTimelineTracker,
|
|
27
27
|
uninstallTimelineTracker,
|
|
28
28
|
getTimeline,
|
|
29
|
-
detectWebFramework
|
|
29
|
+
detectWebFramework,
|
|
30
|
+
resolveValueTrace
|
|
30
31
|
} from "@flotrace/runtime-core";
|
|
31
32
|
|
|
33
|
+
// package.json
|
|
34
|
+
var package_default = {
|
|
35
|
+
name: "@flotrace/runtime",
|
|
36
|
+
version: "2.2.2",
|
|
37
|
+
description: "Runtime package for FloTrace - enables real-time render tracking in your React app",
|
|
38
|
+
main: "./dist/index.js",
|
|
39
|
+
module: "./dist/index.mjs",
|
|
40
|
+
types: "./dist/index.d.ts",
|
|
41
|
+
exports: {
|
|
42
|
+
".": {
|
|
43
|
+
types: "./dist/index.d.ts",
|
|
44
|
+
import: "./dist/index.mjs",
|
|
45
|
+
require: "./dist/index.js"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
files: [
|
|
49
|
+
"dist"
|
|
50
|
+
],
|
|
51
|
+
scripts: {
|
|
52
|
+
build: "tsup",
|
|
53
|
+
dev: "tsup --watch",
|
|
54
|
+
typecheck: "tsc --noEmit",
|
|
55
|
+
clean: "rm -rf dist",
|
|
56
|
+
prepublishOnly: "npm run -w @flotrace/runtime-core build && npm run clean && npm run build && npm run typecheck",
|
|
57
|
+
"release:patch": "npm version patch && npm publish",
|
|
58
|
+
"release:minor": "npm version minor && npm publish",
|
|
59
|
+
"release:major": "npm version major && npm publish"
|
|
60
|
+
},
|
|
61
|
+
dependencies: {
|
|
62
|
+
"@flotrace/runtime-core": "2.2.2"
|
|
63
|
+
},
|
|
64
|
+
peerDependencies: {
|
|
65
|
+
react: ">=16.9.0",
|
|
66
|
+
"@types/react": ">=16.9.0"
|
|
67
|
+
},
|
|
68
|
+
peerDependenciesMeta: {
|
|
69
|
+
"@types/react": {
|
|
70
|
+
optional: true
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
devDependencies: {
|
|
74
|
+
tsup: "^8.0.0",
|
|
75
|
+
typescript: "^5.3.0"
|
|
76
|
+
},
|
|
77
|
+
keywords: [
|
|
78
|
+
"react",
|
|
79
|
+
"devtools",
|
|
80
|
+
"profiler",
|
|
81
|
+
"render",
|
|
82
|
+
"performance",
|
|
83
|
+
"flotrace"
|
|
84
|
+
],
|
|
85
|
+
license: "MIT",
|
|
86
|
+
repository: {
|
|
87
|
+
type: "git",
|
|
88
|
+
url: "https://github.com/flotrace/flotrace.git",
|
|
89
|
+
directory: "packages/runtime"
|
|
90
|
+
},
|
|
91
|
+
publishConfig: {
|
|
92
|
+
access: "public"
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
32
96
|
// src/routerTracker.ts
|
|
33
97
|
var isInstalled = false;
|
|
34
98
|
var debounceTimer = null;
|
|
@@ -559,6 +623,7 @@ function flushBuffer() {
|
|
|
559
623
|
|
|
560
624
|
// src/FloTraceProvider.tsx
|
|
561
625
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
626
|
+
var RUNTIME_VERSION = package_default.version;
|
|
562
627
|
var pendingCleanupTimer = null;
|
|
563
628
|
function safeTrackerOp(name, op) {
|
|
564
629
|
try {
|
|
@@ -604,7 +669,8 @@ function FloTraceProvider({ children, config = {}, stores, reduxStore, queryClie
|
|
|
604
669
|
appName: config.appName ?? deriveWebAppName(),
|
|
605
670
|
appId: config.appId ?? deriveWebAppId(),
|
|
606
671
|
frameworkName: config.frameworkName ?? framework.frameworkName,
|
|
607
|
-
frameworkVersion: config.frameworkVersion ?? framework.frameworkVersion
|
|
672
|
+
frameworkVersion: config.frameworkVersion ?? framework.frameworkVersion,
|
|
673
|
+
runtimeVersion: config.runtimeVersion ?? RUNTIME_VERSION
|
|
608
674
|
};
|
|
609
675
|
const [connected, setConnected] = React.useState(false);
|
|
610
676
|
const trackingOptionsRef = useRef({});
|
|
@@ -742,6 +808,37 @@ function FloTraceProvider({ children, config = {}, stores, reduxStore, queryClie
|
|
|
742
808
|
}
|
|
743
809
|
break;
|
|
744
810
|
}
|
|
811
|
+
// Value Lineage — resolve the origin chain for a prop or hook value.
|
|
812
|
+
case "ext:traceValue": {
|
|
813
|
+
try {
|
|
814
|
+
const trace = resolveValueTrace({
|
|
815
|
+
nodeId: message.nodeId,
|
|
816
|
+
propPath: message.propPath,
|
|
817
|
+
hookPath: message.hookPath
|
|
818
|
+
});
|
|
819
|
+
client3.sendImmediate({
|
|
820
|
+
type: "runtime:valueTrace",
|
|
821
|
+
trace: { requestId: message.requestId, ...trace },
|
|
822
|
+
timestamp: Date.now()
|
|
823
|
+
});
|
|
824
|
+
} catch (error) {
|
|
825
|
+
console.error("[FloTrace] resolveValueTrace threw:", error);
|
|
826
|
+
client3.sendImmediate({
|
|
827
|
+
type: "runtime:valueTrace",
|
|
828
|
+
trace: {
|
|
829
|
+
requestId: message.requestId,
|
|
830
|
+
rootNodeId: message.nodeId,
|
|
831
|
+
rootPropPath: message.propPath,
|
|
832
|
+
rootHookPath: message.hookPath,
|
|
833
|
+
steps: [],
|
|
834
|
+
resolvedAtMs: Date.now(),
|
|
835
|
+
error: "value-not-found"
|
|
836
|
+
},
|
|
837
|
+
timestamp: Date.now()
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
745
842
|
case "ext:startNetworkCapture":
|
|
746
843
|
safeTrackerOp("Network capture start", () => installNetworkTracker(client3));
|
|
747
844
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flotrace/runtime",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "Runtime package for FloTrace - enables real-time render tracking in your React app",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"release:major": "npm version major && npm publish"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@flotrace/runtime-core": "2.
|
|
29
|
+
"@flotrace/runtime-core": "2.2.2"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"react": ">=16.9.0",
|