@flotrace/runtime 2.2.2 → 2.2.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sameer Sitre
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -21,6 +21,34 @@ Source code never leaves your machine. The runtime sends only metadata over `ws:
21
21
 
22
22
  ---
23
23
 
24
+ ## About FloTrace Desktop
25
+
26
+ [**FloTrace Desktop**](https://flotrace.dev) is a free Electron app (macOS / Windows / Linux) that visualizes your React app's component hierarchy in real time. This runtime package is the bridge: drop `<FloTraceProvider>` into your app and the desktop renders the live tree, with full inspection of props, hooks, effects, state, network calls, and render cascades.
27
+
28
+ When `@flotrace/runtime` (this package) is paired with the desktop, you get:
29
+
30
+ - **Live component tree** — React Flow graph, render-flash animation, frequency-based heatmap, breadcrumb bar, search-with-fitView.
31
+ - **Per-node inspection** — props (with diff history), hooks (14 classified types + dep diffs), effects (willRun + dep diffs), component timeline.
32
+ - **State tracking** — Zustand (per-store), Redux (with change highlighting), Router, TanStack Query (with health warnings + wasted-refetch detection), Context.
33
+ - **Render cascade tracing** — trigger log, cascade tree, flame chart, cascade compare modal.
34
+ - **Prop drilling detection** — chain detection (≥3 levels deep), severity badges, heatmap overlay, refactor recommendations.
35
+ - **Network health** — fetch / XHR tracking, method badges, status dots, duplicate detection, API → store causal correlation, pin-to-watch.
36
+ - **React 19 + Next.js** — Actions monitor, concurrent-update signals (useTransition / Suspense), compiler memo health, Next.js App Router detection, RSC payload interception.
37
+ - **Watch expressions** — pin values from 8 sources (Zustand / Redux / Router / Context / Props / Hooks / TanStack Query / API), max 20.
38
+ - **AI Code Review Dashboard** — 6-tab review (Re-renders, Memo, Drilling, Effects, Compiler, Network) with Lighthouse-style scores.
39
+ - **Copy-as-Prompt** — turn any panel into an AI-ready prompt for Cursor / Claude / ChatGPT in one click.
40
+
41
+ How it fits together:
42
+
43
+ ```
44
+ your React app ←→ @flotrace/runtime ←→ ws://localhost:3457 ←→ FloTrace Desktop
45
+ (this package — open source, MIT) (closed-source commercial)
46
+ ```
47
+
48
+ The desktop is free and binds to `127.0.0.1` only by default — your source code, props, and state never leave your machine.
49
+
50
+ ---
51
+
24
52
  ## 30-second setup
25
53
 
26
54
  ```bash
@@ -161,7 +189,7 @@ function MyComponent(props: MyProps) {
161
189
 
162
190
  - Source code never leaves your machine. The runtime sends only metadata (component names, prop types, render counts) over `ws://localhost:3457`.
163
191
  - 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).
192
+ - The desktop is closed-source commercial; this runtime package is **MIT-licensed** and open at [github.com/sameersitre/runtime](https://github.com/sameersitre/runtime).
165
193
 
166
194
  ---
167
195
 
@@ -196,4 +224,8 @@ Type exports: `FloTraceConfig`, `LiveTreeNode`, `SerializedValue`, `HookInfo`, `
196
224
 
197
225
  ## License
198
226
 
199
- MIT. Issues and PRs welcome at [github.com/flotrace](https://github.com/flotrace).
227
+ MIT — see [LICENSE](./LICENSE). Issues and PRs welcome at [github.com/sameersitre/runtime](https://github.com/sameersitre/runtime).
228
+
229
+ ---
230
+
231
+ > **Mirrored from the [flotrace-desktop](https://github.com/sameersitre/flotrace-desktop) monorepo.** This repo is read-only — every release is regenerated by the lockstep publisher in the desktop monorepo. Issues filed here are tracked, but PRs are best opened against the upstream monorepo where the canonical source lives.
package/dist/index.js CHANGED
@@ -50,7 +50,7 @@ var import_runtime_core3 = require("@flotrace/runtime-core");
50
50
  // package.json
51
51
  var package_default = {
52
52
  name: "@flotrace/runtime",
53
- version: "2.2.2",
53
+ version: "2.2.3",
54
54
  description: "Runtime package for FloTrace - enables real-time render tracking in your React app",
55
55
  main: "./dist/index.js",
56
56
  module: "./dist/index.mjs",
@@ -63,7 +63,9 @@ var package_default = {
63
63
  }
64
64
  },
65
65
  files: [
66
- "dist"
66
+ "dist",
67
+ "LICENSE",
68
+ "README.md"
67
69
  ],
68
70
  scripts: {
69
71
  build: "tsup",
@@ -76,7 +78,7 @@ var package_default = {
76
78
  "release:major": "npm version major && npm publish"
77
79
  },
78
80
  dependencies: {
79
- "@flotrace/runtime-core": "2.2.2"
81
+ "@flotrace/runtime-core": "2.2.3"
80
82
  },
81
83
  peerDependencies: {
82
84
  react: ">=16.9.0",
@@ -100,10 +102,13 @@ var package_default = {
100
102
  "flotrace"
101
103
  ],
102
104
  license: "MIT",
105
+ homepage: "https://flotrace.dev",
103
106
  repository: {
104
107
  type: "git",
105
- url: "https://github.com/flotrace/flotrace.git",
106
- directory: "packages/runtime"
108
+ url: "https://github.com/sameersitre/runtime.git"
109
+ },
110
+ bugs: {
111
+ url: "https://github.com/sameersitre/runtime/issues"
107
112
  },
108
113
  publishConfig: {
109
114
  access: "public"
@@ -287,6 +292,7 @@ var requestCounter = 0;
287
292
  var requestIndexMap = /* @__PURE__ */ new Map();
288
293
  var earlyRequestIndexMap = /* @__PURE__ */ new Map();
289
294
  var previousFetch = null;
295
+ var trackedFetchRef = null;
290
296
  var originalXhrOpen = null;
291
297
  var originalXhrSend = null;
292
298
  var originalResponseJson = null;
@@ -328,8 +334,11 @@ function installNetworkTracker(wsClient) {
328
334
  function uninstallNetworkTracker() {
329
335
  if (!isInstalled2 && !isPrewarmed) return;
330
336
  if (previousFetch) {
331
- globalThis.fetch = previousFetch;
337
+ if (globalThis.fetch === trackedFetchRef) {
338
+ globalThis.fetch = previousFetch;
339
+ }
332
340
  previousFetch = null;
341
+ trackedFetchRef = null;
333
342
  }
334
343
  if (originalXhrOpen) {
335
344
  XMLHttpRequest.prototype.open = originalXhrOpen;
@@ -367,10 +376,14 @@ function uninstallNetworkTracker() {
367
376
  function patchFetch() {
368
377
  if (typeof globalThis.fetch !== "function") return;
369
378
  previousFetch = globalThis.fetch;
370
- globalThis.fetch = async function trackedFetch(input, init) {
379
+ const capturedPreviousFetch = previousFetch;
380
+ const trackedFetch = async function trackedFetch2(input, init) {
381
+ if (!isInstalled2 && !isPrewarmed) {
382
+ return capturedPreviousFetch.call(globalThis, input, init);
383
+ }
371
384
  const url = extractUrl(input);
372
385
  if (isNoiseUrl(url)) {
373
- return previousFetch.call(globalThis, input, init);
386
+ return capturedPreviousFetch.call(globalThis, input, init);
374
387
  }
375
388
  const method = (init?.method ?? "GET").toUpperCase();
376
389
  const parsedUrl = parseUrl(url);
@@ -385,7 +398,7 @@ function patchFetch() {
385
398
  }
386
399
  pushEntry({ ...entry });
387
400
  try {
388
- const response = await previousFetch.call(globalThis, input, init);
401
+ const response = await capturedPreviousFetch.call(globalThis, input, init);
389
402
  if (entry.state !== "aborted") {
390
403
  entry.state = response.ok ? "success" : "error";
391
404
  entry.status = response.status;
@@ -408,6 +421,8 @@ function patchFetch() {
408
421
  throw err;
409
422
  }
410
423
  };
424
+ trackedFetchRef = trackedFetch;
425
+ globalThis.fetch = trackedFetch;
411
426
  }
412
427
  function patchXhr() {
413
428
  if (typeof XMLHttpRequest === "undefined") return;
package/dist/index.mjs CHANGED
@@ -33,7 +33,7 @@ import {
33
33
  // package.json
34
34
  var package_default = {
35
35
  name: "@flotrace/runtime",
36
- version: "2.2.2",
36
+ version: "2.2.3",
37
37
  description: "Runtime package for FloTrace - enables real-time render tracking in your React app",
38
38
  main: "./dist/index.js",
39
39
  module: "./dist/index.mjs",
@@ -46,7 +46,9 @@ var package_default = {
46
46
  }
47
47
  },
48
48
  files: [
49
- "dist"
49
+ "dist",
50
+ "LICENSE",
51
+ "README.md"
50
52
  ],
51
53
  scripts: {
52
54
  build: "tsup",
@@ -59,7 +61,7 @@ var package_default = {
59
61
  "release:major": "npm version major && npm publish"
60
62
  },
61
63
  dependencies: {
62
- "@flotrace/runtime-core": "2.2.2"
64
+ "@flotrace/runtime-core": "2.2.3"
63
65
  },
64
66
  peerDependencies: {
65
67
  react: ">=16.9.0",
@@ -83,10 +85,13 @@ var package_default = {
83
85
  "flotrace"
84
86
  ],
85
87
  license: "MIT",
88
+ homepage: "https://flotrace.dev",
86
89
  repository: {
87
90
  type: "git",
88
- url: "https://github.com/flotrace/flotrace.git",
89
- directory: "packages/runtime"
91
+ url: "https://github.com/sameersitre/runtime.git"
92
+ },
93
+ bugs: {
94
+ url: "https://github.com/sameersitre/runtime/issues"
90
95
  },
91
96
  publishConfig: {
92
97
  access: "public"
@@ -276,6 +281,7 @@ var requestCounter = 0;
276
281
  var requestIndexMap = /* @__PURE__ */ new Map();
277
282
  var earlyRequestIndexMap = /* @__PURE__ */ new Map();
278
283
  var previousFetch = null;
284
+ var trackedFetchRef = null;
279
285
  var originalXhrOpen = null;
280
286
  var originalXhrSend = null;
281
287
  var originalResponseJson = null;
@@ -317,8 +323,11 @@ function installNetworkTracker(wsClient) {
317
323
  function uninstallNetworkTracker() {
318
324
  if (!isInstalled2 && !isPrewarmed) return;
319
325
  if (previousFetch) {
320
- globalThis.fetch = previousFetch;
326
+ if (globalThis.fetch === trackedFetchRef) {
327
+ globalThis.fetch = previousFetch;
328
+ }
321
329
  previousFetch = null;
330
+ trackedFetchRef = null;
322
331
  }
323
332
  if (originalXhrOpen) {
324
333
  XMLHttpRequest.prototype.open = originalXhrOpen;
@@ -356,10 +365,14 @@ function uninstallNetworkTracker() {
356
365
  function patchFetch() {
357
366
  if (typeof globalThis.fetch !== "function") return;
358
367
  previousFetch = globalThis.fetch;
359
- globalThis.fetch = async function trackedFetch(input, init) {
368
+ const capturedPreviousFetch = previousFetch;
369
+ const trackedFetch = async function trackedFetch2(input, init) {
370
+ if (!isInstalled2 && !isPrewarmed) {
371
+ return capturedPreviousFetch.call(globalThis, input, init);
372
+ }
360
373
  const url = extractUrl(input);
361
374
  if (isNoiseUrl(url)) {
362
- return previousFetch.call(globalThis, input, init);
375
+ return capturedPreviousFetch.call(globalThis, input, init);
363
376
  }
364
377
  const method = (init?.method ?? "GET").toUpperCase();
365
378
  const parsedUrl = parseUrl(url);
@@ -374,7 +387,7 @@ function patchFetch() {
374
387
  }
375
388
  pushEntry({ ...entry });
376
389
  try {
377
- const response = await previousFetch.call(globalThis, input, init);
390
+ const response = await capturedPreviousFetch.call(globalThis, input, init);
378
391
  if (entry.state !== "aborted") {
379
392
  entry.state = response.ok ? "success" : "error";
380
393
  entry.status = response.status;
@@ -397,6 +410,8 @@ function patchFetch() {
397
410
  throw err;
398
411
  }
399
412
  };
413
+ trackedFetchRef = trackedFetch;
414
+ globalThis.fetch = trackedFetch;
400
415
  }
401
416
  function patchXhr() {
402
417
  if (typeof XMLHttpRequest === "undefined") return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flotrace/runtime",
3
- "version": "2.2.2",
3
+ "version": "2.2.3",
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",
@@ -13,7 +13,9 @@
13
13
  }
14
14
  },
15
15
  "files": [
16
- "dist"
16
+ "dist",
17
+ "LICENSE",
18
+ "README.md"
17
19
  ],
18
20
  "scripts": {
19
21
  "build": "tsup",
@@ -26,7 +28,7 @@
26
28
  "release:major": "npm version major && npm publish"
27
29
  },
28
30
  "dependencies": {
29
- "@flotrace/runtime-core": "2.2.2"
31
+ "@flotrace/runtime-core": "2.2.3"
30
32
  },
31
33
  "peerDependencies": {
32
34
  "react": ">=16.9.0",
@@ -50,10 +52,13 @@
50
52
  "flotrace"
51
53
  ],
52
54
  "license": "MIT",
55
+ "homepage": "https://flotrace.dev",
53
56
  "repository": {
54
57
  "type": "git",
55
- "url": "https://github.com/flotrace/flotrace.git",
56
- "directory": "packages/runtime"
58
+ "url": "https://github.com/sameersitre/runtime.git"
59
+ },
60
+ "bugs": {
61
+ "url": "https://github.com/sameersitre/runtime/issues"
57
62
  },
58
63
  "publishConfig": {
59
64
  "access": "public"