rerender-lens 0.5.0 → 0.7.0

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 (64) hide show
  1. package/CHANGELOG.md +50 -1
  2. package/README.md +23 -4
  3. package/dist/{budget-CRswn-nC.d.cts → budget-CA1MS7lB.d.cts} +1 -1
  4. package/dist/{budget-BnJlYwrV.d.ts → budget-ok1VDJ4t.d.ts} +1 -1
  5. package/dist/cli.cjs +78 -26
  6. package/dist/cli.cjs.map +1 -1
  7. package/dist/cli.js +78 -26
  8. package/dist/cli.js.map +1 -1
  9. package/dist/{devtools-BYWat7nQ.d.ts → devtools-Cl5n_52v.d.ts} +11 -2
  10. package/dist/{devtools-DJi_6AfJ.d.cts → devtools-UwQx2VYS.d.cts} +11 -2
  11. package/dist/index.cjs +99 -9
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +13 -7
  14. package/dist/index.d.ts +13 -7
  15. package/dist/index.js +99 -10
  16. package/dist/index.js.map +1 -1
  17. package/dist/jest-setup.cjs +20 -3
  18. package/dist/jest-setup.cjs.map +1 -1
  19. package/dist/jest-setup.d.cts +4 -4
  20. package/dist/jest-setup.d.ts +4 -4
  21. package/dist/jest-setup.js +20 -3
  22. package/dist/jest-setup.js.map +1 -1
  23. package/dist/jest.cjs +20 -3
  24. package/dist/jest.cjs.map +1 -1
  25. package/dist/jest.d.cts +4 -4
  26. package/dist/jest.d.ts +4 -4
  27. package/dist/jest.js +20 -3
  28. package/dist/jest.js.map +1 -1
  29. package/dist/{notifiers-DwKlvv4H.d.cts → notifiers-B5poAEvE.d.cts} +2 -2
  30. package/dist/{notifiers-FNzKHs0a.d.ts → notifiers-CqQW0Eum.d.ts} +2 -2
  31. package/dist/playwright.d.cts +4 -4
  32. package/dist/playwright.d.ts +4 -4
  33. package/dist/relay.cjs +65 -21
  34. package/dist/relay.cjs.map +1 -1
  35. package/dist/relay.d.cts +25 -3
  36. package/dist/relay.d.ts +25 -3
  37. package/dist/relay.js +65 -21
  38. package/dist/relay.js.map +1 -1
  39. package/dist/rerender-lens.iife.js +105 -12
  40. package/dist/{runner-report-CW8X5RwK.d.ts → runner-report-Bvqoe89M.d.ts} +2 -2
  41. package/dist/{runner-report-B8Sc3FZO.d.cts → runner-report-CvpDg2zt.d.cts} +2 -2
  42. package/dist/setup.cjs +98 -9
  43. package/dist/setup.cjs.map +1 -1
  44. package/dist/setup.js +98 -9
  45. package/dist/setup.js.map +1 -1
  46. package/dist/{types-DW5-N2XH.d.cts → types-DwNN5cWe.d.cts} +28 -1
  47. package/dist/{types-DW5-N2XH.d.ts → types-DwNN5cWe.d.ts} +28 -1
  48. package/dist/vite.d.cts +1 -1
  49. package/dist/vite.d.ts +1 -1
  50. package/dist/vitest-setup.cjs +20 -3
  51. package/dist/vitest-setup.cjs.map +1 -1
  52. package/dist/vitest-setup.d.cts +4 -4
  53. package/dist/vitest-setup.d.ts +4 -4
  54. package/dist/vitest-setup.js +20 -3
  55. package/dist/vitest-setup.js.map +1 -1
  56. package/dist/vitest.cjs +20 -3
  57. package/dist/vitest.cjs.map +1 -1
  58. package/dist/vitest.d.cts +5 -5
  59. package/dist/vitest.d.ts +5 -5
  60. package/dist/vitest.js +20 -3
  61. package/dist/vitest.js.map +1 -1
  62. package/package.json +3 -2
  63. package/panel/panel.css +48 -0
  64. package/panel/panel.js +348 -20
package/dist/index.d.cts CHANGED
@@ -1,13 +1,19 @@
1
- import { O as Options, C as ChangeKind, b as Change, H as HookChange, c as HookSnapshot, P as ParentInfo, d as CommitPriority, S as SourceLocation, e as CommitCause, R as RenderReport, a as ReportLike } from './types-DW5-N2XH.cjs';
2
- export { f as ChangeLike, g as ComponentMatcher, M as MARKER, N as Notifier, h as RenderTrigger } from './types-DW5-N2XH.cjs';
3
- import { F as Fiber } from './devtools-DJi_6AfJ.cjs';
4
- export { C as ChannelCommand, a as ChannelReply, D as DEFAULT_CHANNEL, b as DEVTOOLS_MARKER, c as DevtoolsBridge, d as DevtoolsMessage, e as DevtoolsNotifierOptions, H as HelloPayload, I as InspectResult, P as PROTOCOL_VERSION, f as PullResult, R as RendererInfo, S as SerializableOptions, g as createDevtoolsNotifier, h as deserializeOptions, i as ensureDevtoolsHook, j as getRenderers, k as isProductionReact, s as serialize, l as serializeOptions } from './devtools-DJi_6AfJ.cjs';
5
- export { B as Budget, a as BudgetResult, b as BudgetViolation, F as Fix, d as FixKind, R as RankedFix, e as assertWithinBudget, g as avoidableCounts, c as checkBudget, h as fixKey, i as fixesFor, f as formatFixes, r as rankFixes, s as shortValue, t as toBudget } from './budget-CRswn-nC.cjs';
6
- export { C as Collector, a as CompareRow, b as Comparison, S as SessionSummary, c as combineNotifiers, d as compareSessions, e as compareSummaries, f as createCollector, g as formatComparison, p as parseExport, s as summarizeReports, h as summarizeSession } from './notifiers-DwKlvv4H.cjs';
1
+ import { O as Options, a as TrackingVerdict, C as ChangeKind, c as Change, H as HookChange, d as HookSnapshot, P as ParentInfo, e as CommitPriority, S as SourceLocation, f as CommitCause, R as RenderReport, b as ReportLike } from './types-DwNN5cWe.cjs';
2
+ export { g as ChangeLike, h as ComponentMatcher, M as MARKER, N as Notifier, i as RenderTrigger, T as TrackingSummary } from './types-DwNN5cWe.cjs';
3
+ import { F as Fiber } from './devtools-UwQx2VYS.cjs';
4
+ export { C as ChannelCommand, a as ChannelReply, D as DEFAULT_CHANNEL, b as DEVTOOLS_MARKER, c as DevtoolsBridge, d as DevtoolsMessage, e as DevtoolsNotifierOptions, H as HelloPayload, I as InspectResult, P as PROTOCOL_VERSION, f as PullResult, R as RendererInfo, S as SerializableOptions, g as createDevtoolsNotifier, h as deserializeOptions, i as ensureDevtoolsHook, j as getRenderers, k as isProductionReact, s as serialize, l as serializeOptions } from './devtools-UwQx2VYS.cjs';
5
+ export { B as Budget, a as BudgetResult, b as BudgetViolation, F as Fix, d as FixKind, R as RankedFix, e as assertWithinBudget, g as avoidableCounts, c as checkBudget, h as fixKey, i as fixesFor, f as formatFixes, r as rankFixes, s as shortValue, t as toBudget } from './budget-CA1MS7lB.cjs';
6
+ export { C as Collector, a as CompareRow, b as Comparison, S as SessionSummary, c as combineNotifiers, d as compareSessions, e as compareSummaries, f as createCollector, g as formatComparison, p as parseExport, s as summarizeReports, h as summarizeSession } from './notifiers-B5poAEvE.cjs';
7
7
 
8
8
  declare function getDisplayName(type: unknown): string;
9
9
  /** Decide whether a component type is tracked under the given options. */
10
10
  declare function shouldTrack(type: unknown, o: Options): boolean;
11
+ /**
12
+ * The same decision as `shouldTrack`, with the rule that made it and what to change. Pure and
13
+ * allocation-light, but one step slower than `shouldTrack` (it builds strings), so the commit path
14
+ * keeps calling `shouldTrack`; `test/tracking.test.ts` proves the two never disagree.
15
+ */
16
+ declare function explainTracking(type: unknown, o: Options): TrackingVerdict;
11
17
  /**
12
18
  * Start reporting re-renders of tracked components. Observes React commits
13
19
  * through the DevTools global hook; nothing in React is patched or wrapped.
@@ -247,4 +253,4 @@ declare function formatRootCauses(reports: readonly ReportLike[], limit?: number
247
253
  /** Library version, injected by the build; "dev" when running from source. */
248
254
  declare const VERSION: string;
249
255
 
250
- export { AVOIDABLE_KINDS, type CascadeNode, Change, ChangeKind, type CommitAnalysis, CommitCause, CommitPriority, type ContextStat, type DispatcherRef, HookChange, HookSnapshot, KIND_LABEL, type Leaf, Options, ParentInfo, type RankedRootCause, RenderReport, ReportLike, type RootCause, type RootSummary, SourceLocation, VERSION, analyzeCommit, buildReport, cascadeTree, classify, configure, contextAttribution, customHooksFromStack, deepEqual, diffLeaves, diffRecords, disable, firstDifferentPath, formatRootCauses, getDisplayName, groupByCommit, hookLabel, indexByComponent, init, isEnabled, printReport, rankRootCauses, resolveHookNames, rootCauseOf, rootCauseSummary, shouldTrack, storeAdvice, summarize, track, useWhyRerender };
256
+ export { AVOIDABLE_KINDS, type CascadeNode, Change, ChangeKind, type CommitAnalysis, CommitCause, CommitPriority, type ContextStat, type DispatcherRef, HookChange, HookSnapshot, KIND_LABEL, type Leaf, Options, ParentInfo, type RankedRootCause, RenderReport, ReportLike, type RootCause, type RootSummary, SourceLocation, TrackingVerdict, VERSION, analyzeCommit, buildReport, cascadeTree, classify, configure, contextAttribution, customHooksFromStack, deepEqual, diffLeaves, diffRecords, disable, explainTracking, firstDifferentPath, formatRootCauses, getDisplayName, groupByCommit, hookLabel, indexByComponent, init, isEnabled, printReport, rankRootCauses, resolveHookNames, rootCauseOf, rootCauseSummary, shouldTrack, storeAdvice, summarize, track, useWhyRerender };
package/dist/index.d.ts CHANGED
@@ -1,13 +1,19 @@
1
- import { O as Options, C as ChangeKind, b as Change, H as HookChange, c as HookSnapshot, P as ParentInfo, d as CommitPriority, S as SourceLocation, e as CommitCause, R as RenderReport, a as ReportLike } from './types-DW5-N2XH.js';
2
- export { f as ChangeLike, g as ComponentMatcher, M as MARKER, N as Notifier, h as RenderTrigger } from './types-DW5-N2XH.js';
3
- import { F as Fiber } from './devtools-BYWat7nQ.js';
4
- export { C as ChannelCommand, a as ChannelReply, D as DEFAULT_CHANNEL, b as DEVTOOLS_MARKER, c as DevtoolsBridge, d as DevtoolsMessage, e as DevtoolsNotifierOptions, H as HelloPayload, I as InspectResult, P as PROTOCOL_VERSION, f as PullResult, R as RendererInfo, S as SerializableOptions, g as createDevtoolsNotifier, h as deserializeOptions, i as ensureDevtoolsHook, j as getRenderers, k as isProductionReact, s as serialize, l as serializeOptions } from './devtools-BYWat7nQ.js';
5
- export { B as Budget, a as BudgetResult, b as BudgetViolation, F as Fix, d as FixKind, R as RankedFix, e as assertWithinBudget, g as avoidableCounts, c as checkBudget, h as fixKey, i as fixesFor, f as formatFixes, r as rankFixes, s as shortValue, t as toBudget } from './budget-BnJlYwrV.js';
6
- export { C as Collector, a as CompareRow, b as Comparison, S as SessionSummary, c as combineNotifiers, d as compareSessions, e as compareSummaries, f as createCollector, g as formatComparison, p as parseExport, s as summarizeReports, h as summarizeSession } from './notifiers-FNzKHs0a.js';
1
+ import { O as Options, a as TrackingVerdict, C as ChangeKind, c as Change, H as HookChange, d as HookSnapshot, P as ParentInfo, e as CommitPriority, S as SourceLocation, f as CommitCause, R as RenderReport, b as ReportLike } from './types-DwNN5cWe.js';
2
+ export { g as ChangeLike, h as ComponentMatcher, M as MARKER, N as Notifier, i as RenderTrigger, T as TrackingSummary } from './types-DwNN5cWe.js';
3
+ import { F as Fiber } from './devtools-Cl5n_52v.js';
4
+ export { C as ChannelCommand, a as ChannelReply, D as DEFAULT_CHANNEL, b as DEVTOOLS_MARKER, c as DevtoolsBridge, d as DevtoolsMessage, e as DevtoolsNotifierOptions, H as HelloPayload, I as InspectResult, P as PROTOCOL_VERSION, f as PullResult, R as RendererInfo, S as SerializableOptions, g as createDevtoolsNotifier, h as deserializeOptions, i as ensureDevtoolsHook, j as getRenderers, k as isProductionReact, s as serialize, l as serializeOptions } from './devtools-Cl5n_52v.js';
5
+ export { B as Budget, a as BudgetResult, b as BudgetViolation, F as Fix, d as FixKind, R as RankedFix, e as assertWithinBudget, g as avoidableCounts, c as checkBudget, h as fixKey, i as fixesFor, f as formatFixes, r as rankFixes, s as shortValue, t as toBudget } from './budget-ok1VDJ4t.js';
6
+ export { C as Collector, a as CompareRow, b as Comparison, S as SessionSummary, c as combineNotifiers, d as compareSessions, e as compareSummaries, f as createCollector, g as formatComparison, p as parseExport, s as summarizeReports, h as summarizeSession } from './notifiers-CqQW0Eum.js';
7
7
 
8
8
  declare function getDisplayName(type: unknown): string;
9
9
  /** Decide whether a component type is tracked under the given options. */
10
10
  declare function shouldTrack(type: unknown, o: Options): boolean;
11
+ /**
12
+ * The same decision as `shouldTrack`, with the rule that made it and what to change. Pure and
13
+ * allocation-light, but one step slower than `shouldTrack` (it builds strings), so the commit path
14
+ * keeps calling `shouldTrack`; `test/tracking.test.ts` proves the two never disagree.
15
+ */
16
+ declare function explainTracking(type: unknown, o: Options): TrackingVerdict;
11
17
  /**
12
18
  * Start reporting re-renders of tracked components. Observes React commits
13
19
  * through the DevTools global hook; nothing in React is patched or wrapped.
@@ -247,4 +253,4 @@ declare function formatRootCauses(reports: readonly ReportLike[], limit?: number
247
253
  /** Library version, injected by the build; "dev" when running from source. */
248
254
  declare const VERSION: string;
249
255
 
250
- export { AVOIDABLE_KINDS, type CascadeNode, Change, ChangeKind, type CommitAnalysis, CommitCause, CommitPriority, type ContextStat, type DispatcherRef, HookChange, HookSnapshot, KIND_LABEL, type Leaf, Options, ParentInfo, type RankedRootCause, RenderReport, ReportLike, type RootCause, type RootSummary, SourceLocation, VERSION, analyzeCommit, buildReport, cascadeTree, classify, configure, contextAttribution, customHooksFromStack, deepEqual, diffLeaves, diffRecords, disable, firstDifferentPath, formatRootCauses, getDisplayName, groupByCommit, hookLabel, indexByComponent, init, isEnabled, printReport, rankRootCauses, resolveHookNames, rootCauseOf, rootCauseSummary, shouldTrack, storeAdvice, summarize, track, useWhyRerender };
256
+ export { AVOIDABLE_KINDS, type CascadeNode, Change, ChangeKind, type CommitAnalysis, CommitCause, CommitPriority, type ContextStat, type DispatcherRef, HookChange, HookSnapshot, KIND_LABEL, type Leaf, Options, ParentInfo, type RankedRootCause, RenderReport, ReportLike, type RootCause, type RootSummary, SourceLocation, TrackingVerdict, VERSION, analyzeCommit, buildReport, cascadeTree, classify, configure, contextAttribution, customHooksFromStack, deepEqual, diffLeaves, diffRecords, disable, explainTracking, firstDifferentPath, formatRootCauses, getDisplayName, groupByCommit, hookLabel, indexByComponent, init, isEnabled, printReport, rankRootCauses, resolveHookNames, rootCauseOf, rootCauseSummary, shouldTrack, storeAdvice, summarize, track, useWhyRerender };
package/dist/index.js CHANGED
@@ -401,16 +401,27 @@ function printReport(report, options) {
401
401
  }
402
402
 
403
403
  // src/state.ts
404
+ var MAX_SEEN_COMPONENTS = 500;
404
405
  var KEY = /* @__PURE__ */ Symbol.for("rerender-lens.state");
405
406
  function getState() {
406
407
  const g = globalThis;
407
408
  let s = g[KEY];
408
409
  if (!s) {
409
- s = { options: {}, enabled: false, printed: /* @__PURE__ */ new Map(), detach: null, nextInstanceId: 1, nextCommitId: 1, warnedOnce: /* @__PURE__ */ new Set(), scheduled: 0, commits: 0, overheadMs: 0, maxCommitMs: 0, truncated: 0 };
410
+ s = { options: {}, enabled: false, printed: /* @__PURE__ */ new Map(), detach: null, nextInstanceId: 1, nextCommitId: 1, warnedOnce: /* @__PURE__ */ new Set(), scheduled: 0, commits: 0, overheadMs: 0, maxCommitMs: 0, truncated: 0, seen: /* @__PURE__ */ new Set(), seenTracked: /* @__PURE__ */ new Set(), seenOverflow: false };
410
411
  g[KEY] = s;
411
412
  }
412
413
  return s;
413
414
  }
415
+ function noteRendered(s, name, tracked) {
416
+ if (!s.seen.has(name)) {
417
+ if (s.seen.size >= MAX_SEEN_COMPONENTS) {
418
+ s.seenOverflow = true;
419
+ return;
420
+ }
421
+ s.seen.add(name);
422
+ }
423
+ if (tracked) s.seenTracked.add(name);
424
+ }
414
425
  function warnOnce(key, message) {
415
426
  const s = getState();
416
427
  if (s.warnedOnce.has(key)) return;
@@ -1137,8 +1148,11 @@ function onCommit(root, commitPriority) {
1137
1148
  const alt = fiber.alternate;
1138
1149
  if (alt && isComponentTag(fiber.tag) && didRender(fiber)) {
1139
1150
  if (isHotSwapped(fiber, alt)) hot = true;
1140
- renderedNames.add(fiberName(fiber));
1141
- if (shouldTrack(fiberType(fiber), o)) rendered.push(fiber);
1151
+ const name = fiberName(fiber);
1152
+ renderedNames.add(name);
1153
+ const tracked = shouldTrack(fiberType(fiber), o);
1154
+ noteRendered(s, name, tracked);
1155
+ if (tracked) rendered.push(fiber);
1142
1156
  }
1143
1157
  if (fiber.tag === SuspenseComponent && alt && alt.memoizedState !== null && fiber.memoizedState === null) (resolvedBoundaries ?? (resolvedBoundaries = [])).push(fiber);
1144
1158
  if (!alt || fiber.child !== alt.child) {
@@ -1263,10 +1277,53 @@ function shouldTrack(type, o) {
1263
1277
  if (o.trackAllMemoized) return isMemo(type) || isPureClass(type);
1264
1278
  return false;
1265
1279
  }
1280
+ var ANONYMOUS = "Anonymous";
1281
+ function explainTracking(type, o) {
1282
+ if (typeof type === "string")
1283
+ return { tracked: false, name: type, memoized: false, reason: `<${type}> is a DOM element, not a React component; only components are tracked.` };
1284
+ if (!isComponentLike(type))
1285
+ return { tracked: false, name: ANONYMOUS, memoized: false, reason: "This is not a React component type, so it is never tracked." };
1286
+ const name = getDisplayName(type);
1287
+ const memo = isMemo(type);
1288
+ const memoized = memo || isPureClass(type);
1289
+ if (o.exclude?.some((m) => matches(m, name)))
1290
+ return { tracked: false, name, memoized, reason: `<${name}> matches "exclude", which wins over every other rule.`, fix: `Remove "${name}" from the exclude list.` };
1291
+ if (hasMarker(type)) return { tracked: true, name, memoized, reason: `<${name}> is marked with track() (the ${MARKER} static).` };
1292
+ if (o.include?.some((m) => matches(m, name))) return { tracked: true, name, memoized, reason: `<${name}> matches "include".` };
1293
+ if (o.trackAllComponents) return { tracked: true, name, memoized, reason: '"Track every component" is on, so every component is tracked.' };
1294
+ if (o.trackAllMemoized && memoized)
1295
+ return { tracked: true, name, memoized, reason: `<${name}> is ${memo ? "a React.memo component" : "a PureComponent"}, and "Track every React.memo and PureComponent" is on.` };
1296
+ if (name === ANONYMOUS)
1297
+ return {
1298
+ tracked: false,
1299
+ name,
1300
+ memoized,
1301
+ reason: 'This component has no display name, so "include" and "exclude" cannot address it.',
1302
+ fix: "Give the function a name, set displayName, or mark it with track(fn, 'Name')."
1303
+ };
1304
+ if (o.trackAllMemoized)
1305
+ return {
1306
+ tracked: false,
1307
+ name,
1308
+ memoized,
1309
+ reason: `"Track every React.memo and PureComponent" only covers React.memo components and PureComponent classes, and <${name}> is neither.`,
1310
+ fix: `Add "${name}" to include, wrap it in React.memo, or turn on "Track every component".`
1311
+ };
1312
+ return {
1313
+ tracked: false,
1314
+ name,
1315
+ memoized,
1316
+ reason: `Nothing selects <${name}>: it is not marked with track(), no "include" pattern matches it, and neither "track every" option is on.`,
1317
+ fix: `Add "${name}" to include, or turn on "Track every React.memo and PureComponent" / "Track every component".`
1318
+ };
1319
+ }
1266
1320
  function init(options = {}) {
1267
1321
  const s = getState();
1268
1322
  s.options = { ...options };
1269
1323
  s.printed.clear();
1324
+ s.seen.clear();
1325
+ s.seenTracked.clear();
1326
+ s.seenOverflow = false;
1270
1327
  if (!s.enabled) {
1271
1328
  s.detach = attach();
1272
1329
  s.enabled = true;
@@ -1937,7 +1994,7 @@ function flash(target, duration = 500) {
1937
1994
  }
1938
1995
 
1939
1996
  // src/version.ts
1940
- var VERSION = "0.5.0" ;
1997
+ var VERSION = "0.7.0" ;
1941
1998
 
1942
1999
  // src/devtools.ts
1943
2000
  var DEVTOOLS_MARKER = "__rerenderLens";
@@ -2063,6 +2120,18 @@ function createDevtoolsNotifier(options = {}) {
2063
2120
  target.postMessage(msg, "*");
2064
2121
  };
2065
2122
  const source = options.source ?? "page";
2123
+ const trackingSummary = () => {
2124
+ const s = getState();
2125
+ const o = s.options;
2126
+ return {
2127
+ mode: o.trackAllComponents ? "all" : o.trackAllMemoized ? "memoized" : "marked",
2128
+ include: (o.include ?? []).map(matcherToString).filter((x) => x !== null),
2129
+ exclude: (o.exclude ?? []).map(matcherToString).filter((x) => x !== null),
2130
+ renderedCount: s.seen.size,
2131
+ trackedCount: s.seenTracked.size,
2132
+ overflow: s.seenOverflow
2133
+ };
2134
+ };
2066
2135
  const info = () => ({
2067
2136
  count: buffer.length,
2068
2137
  library: VERSION,
@@ -2076,7 +2145,8 @@ function createDevtoolsNotifier(options = {}) {
2076
2145
  scheduled: getState().scheduled,
2077
2146
  commits: getState().commits,
2078
2147
  overhead: { totalMs: getState().overheadMs, maxCommitMs: getState().maxCommitMs },
2079
- truncated: getState().truncated
2148
+ truncated: getState().truncated,
2149
+ tracking: trackingSummary()
2080
2150
  });
2081
2151
  const bridge = {
2082
2152
  replay: () => {
@@ -2122,6 +2192,10 @@ function createDevtoolsNotifier(options = {}) {
2122
2192
  flashAvoidable: (on) => {
2123
2193
  flashOn = !!on;
2124
2194
  },
2195
+ explain: (target2) => {
2196
+ const comp = typeof target2 === "number" ? fiberById(target2) : nearestComponent(fiberForNode(target2));
2197
+ return comp ? explainTracking(fiberType(comp), getState().options) : null;
2198
+ },
2125
2199
  inspect: (node) => {
2126
2200
  const comp = nearestComponent(fiberForNode(node));
2127
2201
  if (!comp) return null;
@@ -2136,6 +2210,7 @@ function createDevtoolsNotifier(options = {}) {
2136
2210
  component: fiberName(comp),
2137
2211
  instanceId: id,
2138
2212
  tracked: shouldTrack(fiberType(comp), getState().options),
2213
+ tracking: explainTracking(fiberType(comp), getState().options),
2139
2214
  path,
2140
2215
  reports: id === null ? [] : buffer.filter((e) => e.instanceId === id).slice(-20).map((e) => e.payload)
2141
2216
  };
@@ -2170,6 +2245,9 @@ function createDevtoolsNotifier(options = {}) {
2170
2245
  bridge.flashAvoidable(!!data.arg);
2171
2246
  reply.result = true;
2172
2247
  break;
2248
+ case "explain":
2249
+ reply.result = bridge.explain(data.arg);
2250
+ break;
2173
2251
  default:
2174
2252
  reply.error = `unknown command ${String(data.cmd)}`;
2175
2253
  }
@@ -2178,6 +2256,7 @@ function createDevtoolsNotifier(options = {}) {
2178
2256
  }
2179
2257
  return reply;
2180
2258
  };
2259
+ const isRelayGreeting = (data) => !!data && typeof data === "object" && data.__rerenderLensRelay === true && typeof data.app === "string";
2181
2260
  const isCommand = (data) => !!data && typeof data === "object" && data.__rerenderLensCmd === true && typeof data.id === "string";
2182
2261
  const envelope = (type, payload) => ({ [DEVTOOLS_MARKER]: true, version: PROTOCOL_VERSION, type, payload });
2183
2262
  const sinks = [];
@@ -2200,14 +2279,20 @@ function createDevtoolsNotifier(options = {}) {
2200
2279
  const relayUrl = options.relay ?? (typeof window !== "undefined" ? window.__RERENDER_LENS_RELAY__ : void 0);
2201
2280
  const ES = options.eventSource ?? (typeof EventSource === "function" ? EventSource : null);
2202
2281
  if (relayUrl && ES && typeof fetch === "function") {
2203
- const base = relayUrl.replace(/\/$/, "");
2282
+ const [rawBase, relayQuery = ""] = relayUrl.split("?");
2283
+ const base = (rawBase ?? "").replace(/\/$/, "");
2284
+ const relayToken = new URLSearchParams(relayQuery).get("token");
2285
+ const auth = relayToken ? `token=${encodeURIComponent(relayToken)}` : "";
2204
2286
  let queue = [];
2205
2287
  let scheduled = false;
2288
+ let appId = null;
2206
2289
  const flush = () => {
2207
2290
  scheduled = false;
2208
2291
  const batch = queue;
2209
2292
  queue = [];
2210
- fetch(`${base}/message`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(batch), keepalive: true }).catch(() => {
2293
+ const params = [appId ? `app=${encodeURIComponent(appId)}` : "", auth].filter(Boolean).join("&");
2294
+ const to = `${base}/message${params ? `?${params}` : ""}`;
2295
+ fetch(to, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(batch), keepalive: true }).catch(() => {
2211
2296
  });
2212
2297
  };
2213
2298
  const relaySend = (message) => {
@@ -2218,7 +2303,8 @@ function createDevtoolsNotifier(options = {}) {
2218
2303
  }
2219
2304
  };
2220
2305
  try {
2221
- const stream = new ES(`${base}/events?role=app`);
2306
+ const label = typeof location !== "undefined" ? `${location.host}${location.pathname}`.slice(0, 120) : "";
2307
+ const stream = new ES(`${base}/events?role=app${label ? `&label=${encodeURIComponent(label)}` : ""}${auth ? `&${auth}` : ""}`);
2222
2308
  stream.onmessage = (event) => {
2223
2309
  let parsed;
2224
2310
  try {
@@ -2226,7 +2312,10 @@ function createDevtoolsNotifier(options = {}) {
2226
2312
  } catch {
2227
2313
  return;
2228
2314
  }
2229
- for (const m of Array.isArray(parsed) ? parsed : [parsed]) if (isCommand(m)) relaySend(runCommand(m));
2315
+ for (const m of Array.isArray(parsed) ? parsed : [parsed]) {
2316
+ if (isRelayGreeting(m)) appId = m.app;
2317
+ else if (isCommand(m)) relaySend(runCommand(m));
2318
+ }
2230
2319
  };
2231
2320
  stream.onerror = () => {
2232
2321
  };
@@ -2269,6 +2358,6 @@ function createDevtoolsNotifier(options = {}) {
2269
2358
  };
2270
2359
  }
2271
2360
 
2272
- export { AVOIDABLE_KINDS, DEFAULT_CHANNEL, DEVTOOLS_MARKER, KIND_LABEL, MARKER, PROTOCOL_VERSION, VERSION, analyzeCommit, assertWithinBudget, avoidableCounts, buildReport, cascadeTree, checkBudget, classify, combineNotifiers, compareSessions, compareSummaries, configure, contextAttribution, createCollector, createDevtoolsNotifier, customHooksFromStack, deepEqual, deserializeOptions, diffLeaves, diffRecords, disable, ensureDevtoolsHook, firstDifferentPath, fixKey, fixesFor, formatComparison, formatFixes, formatRootCauses, getDisplayName, getRenderers, groupByCommit, hookLabel, indexByComponent, init, isEnabled, isProductionReact, parseExport, printReport, rankFixes, rankRootCauses, resolveHookNames, rootCauseOf, rootCauseSummary, serialize, serializeOptions, shortValue, shouldTrack, storeAdvice, summarize, summarizeReports, summarizeSession, toBudget, track, useWhyRerender };
2361
+ export { AVOIDABLE_KINDS, DEFAULT_CHANNEL, DEVTOOLS_MARKER, KIND_LABEL, MARKER, PROTOCOL_VERSION, VERSION, analyzeCommit, assertWithinBudget, avoidableCounts, buildReport, cascadeTree, checkBudget, classify, combineNotifiers, compareSessions, compareSummaries, configure, contextAttribution, createCollector, createDevtoolsNotifier, customHooksFromStack, deepEqual, deserializeOptions, diffLeaves, diffRecords, disable, ensureDevtoolsHook, explainTracking, firstDifferentPath, fixKey, fixesFor, formatComparison, formatFixes, formatRootCauses, getDisplayName, getRenderers, groupByCommit, hookLabel, indexByComponent, init, isEnabled, isProductionReact, parseExport, printReport, rankFixes, rankRootCauses, resolveHookNames, rootCauseOf, rootCauseSummary, serialize, serializeOptions, shortValue, shouldTrack, storeAdvice, summarize, summarizeReports, summarizeSession, toBudget, track, useWhyRerender };
2273
2362
  //# sourceMappingURL=index.js.map
2274
2363
  //# sourceMappingURL=index.js.map