@flotrace/runtime-core 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 +21 -0
- package/README.md +33 -2
- package/dist/index.js +13 -5
- package/dist/index.mjs +13 -5
- package/package.json +9 -4
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
|
@@ -11,6 +11,33 @@ Platform-agnostic core for [FloTrace](https://flotrace.dev) — fiber walker, ho
|
|
|
11
11
|
|
|
12
12
|
`runtime-core` is published publicly so adapters can pin a compatible version and so users can audit the open-source half of FloTrace. It has zero runtime dependency on `window` / `document` / `XMLHttpRequest` — all platform-specific features live in the adapters.
|
|
13
13
|
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## About FloTrace Desktop
|
|
17
|
+
|
|
18
|
+
[**FloTrace Desktop**](https://flotrace.dev) is a free Electron app (macOS / Windows / Linux) that visualizes a running React app's component hierarchy in real time. It pairs with this runtime over a local WebSocket on port `3457` — the runtime sits inside your app and emits metadata; the desktop app renders the live tree, props, hooks, effects, and state. **Source code never leaves your machine.**
|
|
19
|
+
|
|
20
|
+
What you get when this runtime is paired with the desktop:
|
|
21
|
+
|
|
22
|
+
- **Live component tree** — React Flow graph, render-flash animation, frequency-based heatmap, breadcrumb navigation.
|
|
23
|
+
- **Per-node inspection** — props (with diff history), hooks (14 classified types + dep diffs), effects (willRun + dep diffs), component timeline.
|
|
24
|
+
- **State tracking** — Zustand (per-store), Redux (with change highlighting), Router, TanStack Query (with health warnings + wasted-refetch detection), Context.
|
|
25
|
+
- **Render cascade tracing** — trigger log, cascade tree, flame chart, cascade compare modal.
|
|
26
|
+
- **Prop drilling detection** — chain detection (≥3 levels deep), severity badges, heatmap overlay, refactor recommendations.
|
|
27
|
+
- **Network health** — fetch / XHR tracking, method badges, status dots, duplicate detection, API → store causal correlation.
|
|
28
|
+
- **Watch expressions** — pin values from 8 sources (Zustand / Redux / Router / Context / Props / Hooks / TanStack Query / API).
|
|
29
|
+
- **AI Code Review Dashboard** — 6-tab review (Re-renders, Memo, Drilling, Effects, Compiler, Network) with Lighthouse-style scores.
|
|
30
|
+
- **Copy-as-Prompt** — turn any panel into an AI-ready prompt for Cursor / Claude / ChatGPT in one click.
|
|
31
|
+
|
|
32
|
+
How it fits together:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
your React app ←→ @flotrace/runtime[-native] ←→ ws://localhost:3457 ←→ FloTrace Desktop
|
|
36
|
+
(this stack — open source, MIT) (closed-source commercial)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
[**Download FloTrace Desktop →**](https://flotrace.dev) · [Docs](https://flotrace.dev/docs) · [Security model](https://flotrace.dev/security)
|
|
40
|
+
|
|
14
41
|
## What's inside
|
|
15
42
|
|
|
16
43
|
| Module | Purpose |
|
|
@@ -38,8 +65,12 @@ The runtime is what lives inside your app. Open-source means you can read every
|
|
|
38
65
|
|
|
39
66
|
## Contributing
|
|
40
67
|
|
|
41
|
-
Issues and PRs welcome at [github.com/
|
|
68
|
+
Issues and PRs welcome at [github.com/sameersitre/runtime-core](https://github.com/sameersitre/runtime-core). The runtime packages target Hermes, V8 (Chromium), and JavaScriptCore — please test against all three when changing fiber-walker or serializer code.
|
|
42
69
|
|
|
43
70
|
## License
|
|
44
71
|
|
|
45
|
-
MIT.
|
|
72
|
+
MIT — see [LICENSE](./LICENSE).
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
> **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
|
@@ -1847,20 +1847,23 @@ function extractRoute(url) {
|
|
|
1847
1847
|
var originalFetch = null;
|
|
1848
1848
|
var interceptorClient = null;
|
|
1849
1849
|
var isInstalled2 = false;
|
|
1850
|
+
var patchedFetchRef = null;
|
|
1850
1851
|
function installRscPayloadInterceptor(client2) {
|
|
1851
1852
|
if (isInstalled2 || typeof globalThis.fetch !== "function") return;
|
|
1852
1853
|
isInstalled2 = true;
|
|
1853
1854
|
interceptorClient = client2;
|
|
1854
1855
|
originalFetch = globalThis.fetch;
|
|
1855
|
-
|
|
1856
|
+
const capturedOriginalFetch = originalFetch;
|
|
1857
|
+
const capturedClient = client2;
|
|
1858
|
+
const patchedFetch = async function patchedFetch2(input, init) {
|
|
1856
1859
|
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
1857
1860
|
const isRscRequest = RSC_URL_PATTERNS.some((p) => p.test(url));
|
|
1858
|
-
const response = await
|
|
1859
|
-
if (isRscRequest && interceptorClient
|
|
1861
|
+
const response = await capturedOriginalFetch.call(globalThis, input, init);
|
|
1862
|
+
if (isRscRequest && interceptorClient === capturedClient && capturedClient.connected) {
|
|
1860
1863
|
try {
|
|
1861
1864
|
const sizeHeader = response.headers.get("content-length");
|
|
1862
1865
|
const payloadSizeBytes = sizeHeader ? parseInt(sizeHeader, 10) : 0;
|
|
1863
|
-
|
|
1866
|
+
capturedClient.send({
|
|
1864
1867
|
type: "runtime:rscPayload",
|
|
1865
1868
|
route: extractRoute(url),
|
|
1866
1869
|
payloadSizeBytes: isNaN(payloadSizeBytes) ? 0 : payloadSizeBytes,
|
|
@@ -1872,11 +1875,16 @@ function installRscPayloadInterceptor(client2) {
|
|
|
1872
1875
|
}
|
|
1873
1876
|
return response;
|
|
1874
1877
|
};
|
|
1878
|
+
patchedFetchRef = patchedFetch;
|
|
1879
|
+
globalThis.fetch = patchedFetch;
|
|
1875
1880
|
}
|
|
1876
1881
|
function uninstallRscPayloadInterceptor() {
|
|
1877
1882
|
if (!isInstalled2 || !originalFetch) return;
|
|
1878
|
-
globalThis.fetch
|
|
1883
|
+
if (globalThis.fetch === patchedFetchRef) {
|
|
1884
|
+
globalThis.fetch = originalFetch;
|
|
1885
|
+
}
|
|
1879
1886
|
originalFetch = null;
|
|
1887
|
+
patchedFetchRef = null;
|
|
1880
1888
|
interceptorClient = null;
|
|
1881
1889
|
isInstalled2 = false;
|
|
1882
1890
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1765,20 +1765,23 @@ function extractRoute(url) {
|
|
|
1765
1765
|
var originalFetch = null;
|
|
1766
1766
|
var interceptorClient = null;
|
|
1767
1767
|
var isInstalled2 = false;
|
|
1768
|
+
var patchedFetchRef = null;
|
|
1768
1769
|
function installRscPayloadInterceptor(client2) {
|
|
1769
1770
|
if (isInstalled2 || typeof globalThis.fetch !== "function") return;
|
|
1770
1771
|
isInstalled2 = true;
|
|
1771
1772
|
interceptorClient = client2;
|
|
1772
1773
|
originalFetch = globalThis.fetch;
|
|
1773
|
-
|
|
1774
|
+
const capturedOriginalFetch = originalFetch;
|
|
1775
|
+
const capturedClient = client2;
|
|
1776
|
+
const patchedFetch = async function patchedFetch2(input, init) {
|
|
1774
1777
|
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
1775
1778
|
const isRscRequest = RSC_URL_PATTERNS.some((p) => p.test(url));
|
|
1776
|
-
const response = await
|
|
1777
|
-
if (isRscRequest && interceptorClient
|
|
1779
|
+
const response = await capturedOriginalFetch.call(globalThis, input, init);
|
|
1780
|
+
if (isRscRequest && interceptorClient === capturedClient && capturedClient.connected) {
|
|
1778
1781
|
try {
|
|
1779
1782
|
const sizeHeader = response.headers.get("content-length");
|
|
1780
1783
|
const payloadSizeBytes = sizeHeader ? parseInt(sizeHeader, 10) : 0;
|
|
1781
|
-
|
|
1784
|
+
capturedClient.send({
|
|
1782
1785
|
type: "runtime:rscPayload",
|
|
1783
1786
|
route: extractRoute(url),
|
|
1784
1787
|
payloadSizeBytes: isNaN(payloadSizeBytes) ? 0 : payloadSizeBytes,
|
|
@@ -1790,11 +1793,16 @@ function installRscPayloadInterceptor(client2) {
|
|
|
1790
1793
|
}
|
|
1791
1794
|
return response;
|
|
1792
1795
|
};
|
|
1796
|
+
patchedFetchRef = patchedFetch;
|
|
1797
|
+
globalThis.fetch = patchedFetch;
|
|
1793
1798
|
}
|
|
1794
1799
|
function uninstallRscPayloadInterceptor() {
|
|
1795
1800
|
if (!isInstalled2 || !originalFetch) return;
|
|
1796
|
-
globalThis.fetch
|
|
1801
|
+
if (globalThis.fetch === patchedFetchRef) {
|
|
1802
|
+
globalThis.fetch = originalFetch;
|
|
1803
|
+
}
|
|
1797
1804
|
originalFetch = null;
|
|
1805
|
+
patchedFetchRef = null;
|
|
1798
1806
|
interceptorClient = null;
|
|
1799
1807
|
isInstalled2 = false;
|
|
1800
1808
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flotrace/runtime-core",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.3",
|
|
4
4
|
"description": "Platform-agnostic core for FloTrace runtime — fiber walker, analyzers, trackers. Shared by @flotrace/runtime (web) and @flotrace/runtime-native (React Native).",
|
|
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",
|
|
@@ -46,10 +48,13 @@
|
|
|
46
48
|
"flotrace"
|
|
47
49
|
],
|
|
48
50
|
"license": "MIT",
|
|
51
|
+
"homepage": "https://flotrace.dev",
|
|
49
52
|
"repository": {
|
|
50
53
|
"type": "git",
|
|
51
|
-
"url": "https://github.com/
|
|
52
|
-
|
|
54
|
+
"url": "https://github.com/sameersitre/runtime-core.git"
|
|
55
|
+
},
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/sameersitre/runtime-core/issues"
|
|
53
58
|
},
|
|
54
59
|
"publishConfig": {
|
|
55
60
|
"access": "public"
|