@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 CHANGED
@@ -1,24 +1,31 @@
1
1
  # @flotrace/runtime
2
2
 
3
- Runtime package for FloTrace enables real-time React component tree visualization, render tracking, state management monitoring, and network health analysis in the FloTrace desktop app.
3
+ **Stop guessing why your React app re-renders.**
4
4
 
5
- > **Using React Native?** Install [`@flotrace/runtime-native`](https://www.npmjs.com/package/@flotrace/runtime-native) instead. It's the dedicated adapter for iOS / Android`@flotrace/runtime` patches `fetch`, `XMLHttpRequest`, `JSON.parse`, and `Response.prototype.json` in ways that crash the React Native JS bridge. See the [migration guide](../../docs/migration-runtime-native.md) if you're switching a shared codebase.
5
+ FloTrace is a desktop app that shows you, live, what your React tree is doingevery render, every prop change, every state mutation, every cascade without leaving your editor and without uploading your source code anywhere.
6
6
 
7
- ## Installation
7
+ This package is the runtime that wires your app into the desktop. Drop it in once and you get:
8
8
 
9
- ```bash
10
- npm install -D @flotrace/runtime
11
- # or
12
- yarn add -D @flotrace/runtime
13
- # or
14
- pnpm add -D @flotrace/runtime
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
- **Peer dependencies:** React >= 16.9.0 (requires `<Profiler>` API)
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
- ## Quick Start
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
- Wrap your app with `<FloTraceProvider>`:
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
- Then launch the FloTrace desktop app your component tree will appear automatically.
42
+ Launch the FloTrace desktop app. Reload your dev server. Done your tree appears.
36
43
 
37
- ## Configuration
44
+ **Peer dependencies:** React >= 16.9.0 (uses `<Profiler>` API). Auto-disables in production via `process.env.NODE_ENV`.
38
45
 
39
- All config options are optional. Pass them via the `config` prop:
46
+ ---
40
47
 
41
- ```tsx
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
- createRoot(document.getElementById('root')!).render(
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
- ## State Management Integration
88
+ ---
139
89
 
140
- ### Zustand
90
+ ## Wire up your state stores
141
91
 
142
- Pass Zustand stores via the `stores` prop. Keys become store names in FloTrace:
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 './store/bearStore';
147
- import { useUserStore } from './store/userStore';
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
- ### Redux
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
- <FloTraceProvider
166
- reduxStore={store}
167
- config={{ appName: 'My App' }}
168
- >
169
- <App />
170
- </FloTraceProvider>
171
- ```
112
+ ---
172
113
 
173
- ### TanStack Query
114
+ ## Configuration
174
115
 
175
- Pass your TanStack Query client via the `queryClient` prop:
116
+ All options optional. Sensible defaults for development.
176
117
 
177
- ```tsx
178
- import { FloTraceProvider } from '@flotrace/runtime';
179
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
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
- const queryClient = new QueryClient();
129
+ ---
182
130
 
183
- <QueryClientProvider client={queryClient}>
184
- <FloTraceProvider
185
- queryClient={queryClient}
186
- config={{ appName: 'My App' }}
187
- >
188
- <App />
189
- </FloTraceProvider>
190
- </QueryClientProvider>
191
- ```
131
+ ## Production safety
192
132
 
193
- ### Combined (Zustand + Redux + TanStack Query + Router)
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
- import { FloTraceProvider } from '@flotrace/runtime';
197
- import { store } from './reduxStore';
198
- import { useBearStore } from './zustandStore';
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
- Router tracking is automatic — no configuration needed. It works with any SPA router (React Router, TanStack Router, Next.js, etc.) by patching the browser's History API.
141
+ ---
212
142
 
213
- ## Advanced Usage
143
+ ## Targeted profiling
214
144
 
215
- ### `withFloTrace()` HOC for targeted profiling
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
- Call at the top of a component to track its prop changes:
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
- // ... rest of component
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
- ## Production Safety
158
+ ---
250
159
 
251
- By default, FloTrace is **disabled in production** (`enabled` defaults to `process.env.NODE_ENV === 'development'`).
160
+ ## Privacy & security
252
161
 
253
- For explicit control, use a conditional import pattern:
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
- ```tsx
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
- ### "Not connected"
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
- - The fiber tree walker needs React DevTools hook or DOM-based fiber access
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
- ### WebSocket keeps reconnecting
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
- - FloTrace uses exponential backoff (2s → 4s 8s... up to 30s) with a 10-attempt budget
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
- ## API Reference
178
+ ---
291
179
 
292
- ### Components
180
+ ## API reference
293
181
 
294
- | Export | Description |
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
- | `getWebSocketClient(config?)` | Get singleton WebSocket client |
331
- | `disposeWebSocketClient()` | Dispose the WebSocket client |
332
- | `FloTraceWebSocketClient` | WebSocket client class |
333
- | `installFiberTreeWalker()` | Manually install fiber tree walker |
334
- | `uninstallFiberTreeWalker()` | Uninstall fiber tree walker |
335
- | `requestTreeSnapshot()` | Request a tree snapshot (DOM fallback) |
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
- | Script | Action |
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
- > **Note:** `runtime:publish` publishes whatever version is currently in `package.json`. Use this for the first publish or to re-publish a fixed build without bumping the version. The `release:*` scripts auto-increment the version, create a git commit + tag, then publish.
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.0.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.0.1"
29
+ "@flotrace/runtime-core": "2.2.2"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": ">=16.9.0",