react-native-debug-toolkit 3.1.3 → 3.1.4

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 (86) hide show
  1. package/README.md +4 -2
  2. package/README.zh-CN.md +4 -2
  3. package/lib/commonjs/core/DebugToolkit.js +118 -97
  4. package/lib/commonjs/core/DebugToolkit.js.map +1 -1
  5. package/lib/commonjs/core/initialize.js +4 -4
  6. package/lib/commonjs/core/initialize.js.map +1 -1
  7. package/lib/commonjs/features/environment/index.js +22 -24
  8. package/lib/commonjs/features/environment/index.js.map +1 -1
  9. package/lib/commonjs/features/network/index.js +25 -47
  10. package/lib/commonjs/features/network/index.js.map +1 -1
  11. package/lib/commonjs/features/network/networkInterceptor.js +3 -3
  12. package/lib/commonjs/features/network/networkInterceptor.js.map +1 -1
  13. package/lib/commonjs/index.js +0 -30
  14. package/lib/commonjs/index.js.map +1 -1
  15. package/lib/commonjs/utils/DaemonClient.js +13 -51
  16. package/lib/commonjs/utils/DaemonClient.js.map +1 -1
  17. package/lib/commonjs/utils/createChannelFeature.js +8 -1
  18. package/lib/commonjs/utils/createChannelFeature.js.map +1 -1
  19. package/lib/commonjs/utils/deviceReport.js +2 -1
  20. package/lib/commonjs/utils/deviceReport.js.map +1 -1
  21. package/lib/commonjs/utils/urlRewriter.js +15 -0
  22. package/lib/commonjs/utils/urlRewriter.js.map +1 -0
  23. package/lib/module/core/DebugToolkit.js +117 -96
  24. package/lib/module/core/DebugToolkit.js.map +1 -1
  25. package/lib/module/core/initialize.js +6 -7
  26. package/lib/module/core/initialize.js.map +1 -1
  27. package/lib/module/features/environment/index.js +22 -24
  28. package/lib/module/features/environment/index.js.map +1 -1
  29. package/lib/module/features/network/index.js +25 -46
  30. package/lib/module/features/network/index.js.map +1 -1
  31. package/lib/module/features/network/networkInterceptor.js +3 -3
  32. package/lib/module/features/network/networkInterceptor.js.map +1 -1
  33. package/lib/module/index.js +1 -1
  34. package/lib/module/index.js.map +1 -1
  35. package/lib/module/utils/DaemonClient.js +14 -42
  36. package/lib/module/utils/DaemonClient.js.map +1 -1
  37. package/lib/module/utils/createChannelFeature.js +8 -1
  38. package/lib/module/utils/createChannelFeature.js.map +1 -1
  39. package/lib/module/utils/deviceReport.js +3 -2
  40. package/lib/module/utils/deviceReport.js.map +1 -1
  41. package/lib/module/utils/urlRewriter.js +10 -0
  42. package/lib/module/utils/urlRewriter.js.map +1 -0
  43. package/lib/typescript/src/core/DebugToolkit.d.ts +23 -10
  44. package/lib/typescript/src/core/DebugToolkit.d.ts.map +1 -1
  45. package/lib/typescript/src/core/initialize.d.ts.map +1 -1
  46. package/lib/typescript/src/features/environment/index.d.ts.map +1 -1
  47. package/lib/typescript/src/features/network/index.d.ts +3 -3
  48. package/lib/typescript/src/features/network/index.d.ts.map +1 -1
  49. package/lib/typescript/src/index.d.ts +2 -2
  50. package/lib/typescript/src/index.d.ts.map +1 -1
  51. package/lib/typescript/src/types/feature.d.ts +5 -0
  52. package/lib/typescript/src/types/feature.d.ts.map +1 -1
  53. package/lib/typescript/src/types/index.d.ts +1 -1
  54. package/lib/typescript/src/types/index.d.ts.map +1 -1
  55. package/lib/typescript/src/utils/DaemonClient.d.ts +4 -11
  56. package/lib/typescript/src/utils/DaemonClient.d.ts.map +1 -1
  57. package/lib/typescript/src/utils/createChannelFeature.d.ts +4 -0
  58. package/lib/typescript/src/utils/createChannelFeature.d.ts.map +1 -1
  59. package/lib/typescript/src/utils/deviceReport.d.ts +4 -1
  60. package/lib/typescript/src/utils/deviceReport.d.ts.map +1 -1
  61. package/lib/typescript/src/utils/urlRewriter.d.ts +5 -0
  62. package/lib/typescript/src/utils/urlRewriter.d.ts.map +1 -0
  63. package/node/daemon/src/console/console.html +94 -15
  64. package/node/daemon/src/server.js +32 -2
  65. package/node/mcp/src/logs.js +15 -4
  66. package/node/mcp/src/tools.js +4 -2
  67. package/package.json +1 -1
  68. package/src/core/DebugToolkit.tsx +119 -105
  69. package/src/core/initialize.ts +7 -8
  70. package/src/features/environment/index.ts +25 -27
  71. package/src/features/network/index.ts +30 -52
  72. package/src/features/network/networkInterceptor.ts +3 -3
  73. package/src/index.ts +3 -8
  74. package/src/types/feature.ts +6 -0
  75. package/src/types/index.ts +1 -0
  76. package/src/utils/DaemonClient.ts +14 -56
  77. package/src/utils/createChannelFeature.ts +12 -1
  78. package/src/utils/deviceReport.ts +5 -3
  79. package/src/utils/urlRewriter.ts +11 -0
  80. package/lib/commonjs/utils/urlRewriterRegistry.js +0 -14
  81. package/lib/commonjs/utils/urlRewriterRegistry.js.map +0 -1
  82. package/lib/module/utils/urlRewriterRegistry.js +0 -10
  83. package/lib/module/utils/urlRewriterRegistry.js.map +0 -1
  84. package/lib/typescript/src/utils/urlRewriterRegistry.d.ts +0 -7
  85. package/lib/typescript/src/utils/urlRewriterRegistry.d.ts.map +0 -1
  86. package/src/utils/urlRewriterRegistry.ts +0 -10
@@ -1,176 +1,190 @@
1
- import type { AnyDebugFeature } from '../types';
1
+ import type { AnyDebugFeature, DebugFeatureListener, FeatureDataProvider } from '../types';
2
2
 
3
- type Listener = () => void;
3
+ class DebugToolkitCore implements FeatureDataProvider {
4
+ private _features: AnyDebugFeature[] = [];
5
+ private _launcherVisible = false;
6
+ private _panelOpen = false;
7
+ private _enabled = true;
8
+ private _listeners = new Set<DebugFeatureListener>();
4
9
 
5
- const listeners = new Set<Listener>();
6
- let _features: AnyDebugFeature[] = [];
7
- let _launcherVisible = false;
8
- let _panelOpen = false;
9
- let _enabled = true;
10
+ private notify(): void {
11
+ this._listeners.forEach((l) => l());
12
+ }
10
13
 
11
- function notify(): void {
12
- listeners.forEach((l) => l());
13
- }
14
-
15
- function setupFeature(feature: AnyDebugFeature): void {
16
- feature.setup?.();
17
- }
14
+ // --- FeatureDataProvider ---
18
15
 
19
- function cleanupFeature(feature: AnyDebugFeature): void {
20
- feature.cleanup?.();
21
- }
16
+ get features(): AnyDebugFeature[] {
17
+ return [...this._features];
18
+ }
22
19
 
23
- export const DebugToolkit = {
24
- subscribe(listener: Listener): () => void {
25
- listeners.add(listener);
20
+ subscribe(listener: DebugFeatureListener): () => void {
21
+ this._listeners.add(listener);
26
22
  return () => {
27
- listeners.delete(listener);
23
+ this._listeners.delete(listener);
28
24
  };
29
- },
25
+ }
30
26
 
31
- get features(): AnyDebugFeature[] {
32
- return [..._features];
33
- },
27
+ // --- Enabled ---
34
28
 
35
29
  get enabled(): boolean {
36
- return _enabled;
37
- },
38
-
39
- get launcherVisible(): boolean {
40
- return _launcherVisible;
41
- },
30
+ return this._enabled;
31
+ }
42
32
 
43
33
  setEnabled(enabled: boolean): void {
44
- if (_enabled === enabled) return;
45
- _enabled = enabled;
34
+ if (this._enabled === enabled) return;
35
+ this._enabled = enabled;
46
36
  if (!enabled) {
47
- _launcherVisible = false;
48
- _features.forEach(cleanupFeature);
49
- _features = [];
37
+ this._launcherVisible = false;
38
+ this._features.forEach((f) => f.cleanup?.());
39
+ this._features = [];
50
40
  }
51
- notify();
52
- },
41
+ this.notify();
42
+ }
43
+
44
+ // --- Feature Management ---
53
45
 
54
46
  replaceFeatures(features: AnyDebugFeature[]): void {
55
- if (!_enabled) return;
47
+ if (!this._enabled) return;
56
48
  const next = features.filter(
57
49
  (f, i, arr) =>
58
50
  f && typeof f.name === 'string' && arr.findIndex((item) => item.name === f.name) === i,
59
51
  );
60
- const prevMap = new Map(_features.map((f) => [f.name, f]));
52
+ const prevMap = new Map(this._features.map((f) => [f.name, f]));
61
53
  const nextMap = new Map(next.map((f) => [f.name, f]));
62
54
 
63
- _features.forEach((f) => {
64
- if (!nextMap.get(f.name) || nextMap.get(f.name) !== f) cleanupFeature(f);
55
+ this._features.forEach((f) => {
56
+ if (!nextMap.get(f.name) || nextMap.get(f.name) !== f) f.cleanup?.();
65
57
  });
66
58
  next.forEach((f) => {
67
- if (!prevMap.get(f.name) || prevMap.get(f.name) !== f) setupFeature(f);
59
+ if (!prevMap.get(f.name) || prevMap.get(f.name) !== f) f.setup?.();
68
60
  });
69
61
 
70
- _features = next;
71
- notify();
72
- },
62
+ this._features = next;
63
+ this.notify();
64
+ }
73
65
 
74
66
  addFeature(feature: AnyDebugFeature): void {
75
- if (!_enabled || !feature || typeof feature.name !== 'string') {
67
+ if (!this._enabled || !feature || typeof feature.name !== 'string') {
76
68
  return;
77
69
  }
78
70
 
79
- const existingIndex = _features.findIndex((f) => f.name === feature.name);
71
+ const existingIndex = this._features.findIndex((f) => f.name === feature.name);
80
72
  if (existingIndex >= 0) {
81
- const existing = _features[existingIndex]!;
73
+ const existing = this._features[existingIndex]!;
82
74
  if (existing === feature) {
83
75
  return;
84
76
  }
85
77
 
86
- cleanupFeature(existing);
87
- setupFeature(feature);
88
- _features = [
89
- ..._features.slice(0, existingIndex),
78
+ existing.cleanup?.();
79
+ feature.setup?.();
80
+ this._features = [
81
+ ...this._features.slice(0, existingIndex),
90
82
  feature,
91
- ..._features.slice(existingIndex + 1),
83
+ ...this._features.slice(existingIndex + 1),
92
84
  ];
93
- notify();
85
+ this.notify();
94
86
  return;
95
87
  }
96
88
 
97
- setupFeature(feature);
98
- _features = [..._features, feature];
99
- notify();
100
- },
89
+ feature.setup?.();
90
+ this._features = [...this._features, feature];
91
+ this.notify();
92
+ }
101
93
 
102
94
  removeFeature(name: string): void {
103
- if (!_enabled) {
95
+ if (!this._enabled) {
104
96
  return;
105
97
  }
106
98
 
107
- const feature = _features.find((f) => f.name === name);
99
+ const feature = this._features.find((f) => f.name === name);
108
100
  if (!feature) {
109
101
  return;
110
102
  }
111
103
 
112
- cleanupFeature(feature);
113
- _features = _features.filter((f) => f.name !== name);
114
- if (_features.length === 0) {
115
- _launcherVisible = false;
104
+ feature.cleanup?.();
105
+ this._features = this._features.filter((f) => f.name !== name);
106
+ if (this._features.length === 0) {
107
+ this._launcherVisible = false;
116
108
  }
117
- notify();
118
- },
119
-
120
- reset(): void {
121
- _launcherVisible = false;
122
- _panelOpen = false;
123
- _features.forEach(cleanupFeature);
124
- _features = [];
125
- notify();
126
- },
109
+ this.notify();
110
+ }
127
111
 
128
112
  hasFeatures(): boolean {
129
- return _features.length > 0;
130
- },
113
+ return this._features.length > 0;
114
+ }
115
+
116
+ // --- Panel ---
131
117
 
132
118
  get panelOpen(): boolean {
133
- return _panelOpen;
134
- },
119
+ return this._panelOpen;
120
+ }
135
121
 
136
122
  openPanel(): void {
137
- if (!_enabled || _panelOpen) return;
138
- _panelOpen = true;
139
- notify();
140
- },
123
+ if (!this._enabled || this._panelOpen) return;
124
+ this._panelOpen = true;
125
+ this.notify();
126
+ }
141
127
 
142
128
  closePanel(): void {
143
- if (!_panelOpen) return;
144
- _panelOpen = false;
145
- notify();
146
- },
129
+ if (!this._panelOpen) return;
130
+ this._panelOpen = false;
131
+ this.notify();
132
+ }
147
133
 
148
134
  togglePanel(): void {
149
- if (_panelOpen) {
150
- DebugToolkit.closePanel();
135
+ if (this._panelOpen) {
136
+ this.closePanel();
151
137
  } else {
152
- DebugToolkit.openPanel();
138
+ this.openPanel();
153
139
  }
154
- },
140
+ }
141
+
142
+ // --- Launcher ---
143
+
144
+ get launcherVisible(): boolean {
145
+ return this._launcherVisible;
146
+ }
155
147
 
156
148
  showLauncher(): void {
157
- if (!_enabled) return;
158
- _launcherVisible = true;
159
- notify();
160
- },
149
+ if (!this._enabled) return;
150
+ this._launcherVisible = true;
151
+ this.notify();
152
+ }
161
153
 
162
154
  hideLauncher(): void {
163
- _launcherVisible = false;
164
- notify();
165
- },
155
+ if (!this._launcherVisible) return;
156
+ this._launcherVisible = false;
157
+ this.notify();
158
+ }
159
+
160
+ // --- Bulk Operations ---
166
161
 
167
162
  clearAll(): void {
168
- _features.forEach((f) => f.clear?.());
169
- notify();
170
- },
163
+ this._features.forEach((f) => f.clear?.());
164
+ this.notify();
165
+ }
166
+
167
+ reset(): void {
168
+ this._launcherVisible = false;
169
+ this._panelOpen = false;
170
+ this._features.forEach((f) => f.cleanup?.());
171
+ this._features = [];
172
+ this.notify();
173
+ }
171
174
 
172
175
  destroy(): void {
173
- DebugToolkit.reset();
174
- listeners.clear();
175
- },
176
- };
176
+ this.reset();
177
+ this._listeners.clear();
178
+ }
179
+ }
180
+
181
+ /** Module-level default instance for non-React scenarios and backward compatibility. */
182
+ export const debugToolkit = new DebugToolkitCore();
183
+
184
+ export type DebugToolkit = DebugToolkitCore;
185
+
186
+ /**
187
+ * @deprecated Use `debugToolkit` or get instance from `initializeDebugToolkit()`.
188
+ * This is the default module-level instance exported for backward compatibility.
189
+ */
190
+ export const DebugToolkit = debugToolkit;
@@ -1,5 +1,5 @@
1
1
  import { DebugToolkit } from './DebugToolkit';
2
- import { createNetworkFeature } from '../features/network';
2
+ import { createNetworkFeature, addToBlacklist } from '../features/network';
3
3
  import type { NetworkFeatureConfig } from '../features/network';
4
4
  import { createConsoleLogFeature } from '../features/console';
5
5
  import type { ConsoleFeatureConfig } from '../features/console';
@@ -11,16 +11,11 @@ import { createTrackFeature } from '../features/track';
11
11
  import type { TrackFeatureConfig } from '../features/track';
12
12
  import { createEnvironmentFeature } from '../features/environment';
13
13
  import { createClipboardFeature } from '../features/clipboard';
14
- import { daemonClient, restoreDaemonStreaming } from '../utils/DaemonClient';
15
- import { _addDaemonEndpointToNetworkBlacklist } from '../features/network';
14
+ import { daemonClient } from '../utils/DaemonClient';
16
15
  import type { AnyDebugFeature, BuiltInFeatureName } from '../types';
17
16
 
18
17
  const isDebugMode = __DEV__;
19
18
 
20
- daemonClient.setEndpointDetector((url) => {
21
- _addDaemonEndpointToNetworkBlacklist(url);
22
- });
23
-
24
19
  /** Feature-specific configuration map */
25
20
  export interface FeatureConfigs {
26
21
  network?: boolean | NetworkFeatureConfig;
@@ -114,13 +109,17 @@ export function initializeDebugToolkit(
114
109
 
115
110
  DebugToolkit.replaceFeatures(resolvedFeatures);
116
111
 
112
+ daemonClient.setEndpointDetector((url) => {
113
+ addToBlacklist(url);
114
+ });
115
+
117
116
  if (DebugToolkit.hasFeatures()) {
118
117
  DebugToolkit.showLauncher();
119
118
  } else {
120
119
  DebugToolkit.hideLauncher();
121
120
  }
122
121
 
123
- restoreDaemonStreaming().catch(() => {});
122
+ daemonClient.restore().catch(() => {});
124
123
 
125
124
  return DebugToolkit;
126
125
  } catch (error) {
@@ -5,7 +5,7 @@ import type {
5
5
  EnvironmentConfig,
6
6
  EnvironmentState,
7
7
  } from '../../types';
8
- import { urlRewriter } from '../../utils/urlRewriterRegistry';
8
+ import { setUrlRewriter } from '../../utils/urlRewriter';
9
9
 
10
10
  // Lazy AsyncStorage loader
11
11
  type AsyncStorageModule = {
@@ -32,10 +32,6 @@ function getAsyncStorage(): AsyncStorageModule | null {
32
32
 
33
33
  const STORAGE_KEY = 'debug_toolkit_env_id';
34
34
 
35
- // Module-level state for synchronous URL rewriting
36
- let currentHostsMap: Map<string, string> | null = null;
37
- let activeEnvironmentId: string | null = null;
38
-
39
35
  function buildHostsMap(
40
36
  environments: EnvironmentConfig[],
41
37
  targetId: string | null,
@@ -53,24 +49,6 @@ function buildHostsMap(
53
49
  return map;
54
50
  }
55
51
 
56
- function createUrlRewriter(): (url: string) => string {
57
- return (url: string): string => {
58
- if (!currentHostsMap) return url;
59
-
60
- try {
61
- const parsed = new URL(url);
62
- const targetHost = currentHostsMap.get(parsed.host);
63
- if (targetHost) {
64
- return url.replace(parsed.host, targetHost);
65
- }
66
- } catch {
67
- // Not a valid URL or relative URL — return unchanged
68
- }
69
-
70
- return url;
71
- };
72
- }
73
-
74
52
  export interface EnvironmentFeatureAPI extends DebugFeature<EnvironmentState> {
75
53
  registerEnvironments: (environments: EnvironmentConfig[]) => void;
76
54
  switchEnvironment: (environmentId: string | null) => void;
@@ -83,6 +61,26 @@ export const createEnvironmentFeature = (
83
61
  const listeners = new Set<DebugFeatureListener>();
84
62
  let environments: EnvironmentConfig[] = initialEnvironments ?? [];
85
63
  let initialized = false;
64
+ let currentHostsMap: Map<string, string> | null = null;
65
+ let activeEnvironmentId: string | null = null;
66
+
67
+ const createUrlRewriter = (): ((url: string) => string) => {
68
+ return (url: string): string => {
69
+ if (!currentHostsMap) return url;
70
+
71
+ try {
72
+ const parsed = new URL(url);
73
+ const targetHost = currentHostsMap.get(parsed.host);
74
+ if (targetHost) {
75
+ return url.replace(parsed.host, targetHost);
76
+ }
77
+ } catch {
78
+ // Not a valid URL or relative URL — return unchanged
79
+ }
80
+
81
+ return url;
82
+ };
83
+ };
86
84
 
87
85
  const getCurrentState = (): EnvironmentState => ({
88
86
  environments,
@@ -102,9 +100,9 @@ export const createEnvironmentFeature = (
102
100
  if (initialized) {
103
101
  try {
104
102
  if (envId && environments.length > 0) {
105
- urlRewriter.set(createUrlRewriter());
103
+ setUrlRewriter(createUrlRewriter());
106
104
  } else {
107
- urlRewriter.set(null);
105
+ setUrlRewriter(null);
108
106
  }
109
107
  } catch (err) {
110
108
  if (__DEV__) console.warn('[DebugToolkit] Failed to set URL rewriter:', err);
@@ -149,7 +147,7 @@ export const createEnvironmentFeature = (
149
147
 
150
148
  // Install rewriter if an environment is already selected
151
149
  if (activeEnvironmentId && environments.length > 0) {
152
- urlRewriter.set(createUrlRewriter());
150
+ setUrlRewriter(createUrlRewriter());
153
151
  }
154
152
 
155
153
  // Async persistence load (will override if a preference exists)
@@ -162,7 +160,7 @@ export const createEnvironmentFeature = (
162
160
  },
163
161
  cleanup: () => {
164
162
  if (!initialized) return;
165
- urlRewriter.set(null);
163
+ setUrlRewriter(null);
166
164
  activeEnvironmentId = null;
167
165
  currentHostsMap = null;
168
166
  notify();
@@ -1,15 +1,15 @@
1
1
  import { NetworkLogTab } from './NetworkLogTab';
2
2
 
3
- import type { DebugFeature, NetworkLogEntry } from '../../types';
3
+ import type { NetworkLogEntry } from '../../types';
4
+ import { createChannelFeature } from '../../utils/createChannelFeature';
4
5
  import { createEventChannel } from '../../utils/createEventChannel';
5
- import { createPersistedObservableStore } from '../../utils/createPersistedObservableStore';
6
6
  import { KEYS } from '../../utils/debugPreferences';
7
- import { urlRewriter } from '../../utils/urlRewriterRegistry';
8
7
  import {
9
8
  startXMLHttpRequest,
10
9
  resetInterceptors,
11
10
  } from './networkInterceptor';
12
11
  import type { NetworkLogPayload } from './networkInterceptor';
12
+ import { setUrlRewriter as setInterceptorUrlRewriter } from '../../utils/urlRewriter';
13
13
 
14
14
  // ─── Utilities ────────────────────────────────────────
15
15
 
@@ -35,7 +35,6 @@ function emitNetworkLog(entry: NetworkLogPayload): void {
35
35
 
36
36
  // ─── Feature factory ──────────────────────────────────
37
37
 
38
- const DEFAULT_MAX_LOGS = 200;
39
38
  const daemonEndpointBlacklist: Array<string | RegExp> = [];
40
39
 
41
40
  export interface NetworkFeatureConfig {
@@ -45,54 +44,33 @@ export interface NetworkFeatureConfig {
45
44
  blacklist?: Array<string | RegExp>;
46
45
  }
47
46
 
48
- export const createNetworkFeature = (config?: NetworkFeatureConfig): DebugFeature<NetworkLogEntry[]> => {
49
- const maxLogs = config?.maxLogs ?? DEFAULT_MAX_LOGS;
50
- const blacklist: Array<string | RegExp> = config?.blacklist ? [...config.blacklist] : [];
51
- const logStore = createPersistedObservableStore<NetworkLogEntry>({
52
- storageKey: KEYS.networkLogs,
53
- maxPersist: 30,
54
- });
55
- let initialized = false;
56
- let unsubscribeLogs: (() => void) | null = null;
57
- let stopXhrFn: (() => void) | null = null;
58
-
59
- const handleLog = (entry: NetworkLogPayload) => {
60
- if (isUrlBlacklisted(entry.request.url, [...blacklist, ...daemonEndpointBlacklist])) {
61
- return;
62
- }
63
- logStore.push({ ...entry, id: logStore.nextId() }, maxLogs);
64
- };
65
-
66
- return {
67
- name: 'network',
68
- label: 'Network',
69
- renderContent: NetworkLogTab,
70
- setup: () => {
71
- if (initialized) {
72
- return;
73
- }
74
- unsubscribeLogs = networkChannel.subscribe(handleLog);
75
- stopXhrFn = startXMLHttpRequest(emitNetworkLog);
76
- initialized = true;
47
+ export const createNetworkFeature = (config?: NetworkFeatureConfig) => {
48
+ const userBlacklist = config?.blacklist ? [...config.blacklist] : [];
49
+
50
+ return createChannelFeature<NetworkLogPayload, NetworkLogEntry>(
51
+ () => networkChannel,
52
+ (payload, id) => ({ ...payload, id }),
53
+ {
54
+ name: 'network',
55
+ label: 'Network',
56
+ renderContent: NetworkLogTab,
57
+ maxLogs: config?.maxLogs,
58
+ persist: { storageKey: KEYS.networkLogs, maxPersist: 30 },
59
+ beforePush: (payload) => {
60
+ if (isUrlBlacklisted(payload.request.url, [...userBlacklist, ...daemonEndpointBlacklist])) {
61
+ return null;
62
+ }
63
+ return payload;
64
+ },
65
+ onSetup: () => {
66
+ const stopXhr = startXMLHttpRequest(emitNetworkLog);
67
+ return () => {
68
+ setInterceptorUrlRewriter(null);
69
+ stopXhr();
70
+ };
71
+ },
77
72
  },
78
- getSnapshot: () => logStore.getData(),
79
- clear: () => {
80
- logStore.clear();
81
- },
82
- cleanup: () => {
83
- if (!initialized) {
84
- return;
85
- }
86
- urlRewriter.set(null);
87
- unsubscribeLogs?.();
88
- unsubscribeLogs = null;
89
- stopXhrFn?.();
90
- stopXhrFn = null;
91
- logStore.clear();
92
- initialized = false;
93
- },
94
- subscribe: (listener) => logStore.subscribe(listener),
95
- };
73
+ );
96
74
  };
97
75
 
98
76
  function normalizeDaemonEndpoint(endpoint: string): string {
@@ -109,7 +87,7 @@ function normalizeDaemonEndpoint(endpoint: string): string {
109
87
  }
110
88
  }
111
89
 
112
- export function _addDaemonEndpointToNetworkBlacklist(endpoint: string): void {
90
+ export function addToBlacklist(endpoint: string): void {
113
91
  const normalized = normalizeDaemonEndpoint(endpoint);
114
92
  if (!normalized || daemonEndpointBlacklist.includes(normalized)) {
115
93
  return;
@@ -1,5 +1,5 @@
1
1
  import type { NetworkLogEntry } from '../../types';
2
- import { urlRewriter } from '../../utils/urlRewriterRegistry';
2
+ import { getUrlRewriter } from '../../utils/urlRewriter';
3
3
 
4
4
  type NetworkLogPayload = Omit<NetworkLogEntry, 'id'>;
5
5
 
@@ -11,7 +11,7 @@ export type { NetworkLogPayload };
11
11
  // ─── Shared helpers ────────────────────────────────────
12
12
 
13
13
  function rewriteUrl(url: string): string {
14
- const rewriter = urlRewriter.get();
14
+ const rewriter = getUrlRewriter();
15
15
  if (!rewriter) {
16
16
  return url;
17
17
  }
@@ -193,7 +193,7 @@ export function startXMLHttpRequest(
193
193
  url: string,
194
194
  ...args: unknown[]
195
195
  ) {
196
- const rewrittenUrl = urlRewriter.get() ? rewriteUrl(url) : url;
196
+ const rewrittenUrl = rewriteUrl(url);
197
197
  if (shouldIgnoreUrl(rewrittenUrl)) {
198
198
  return originalXhrOpen!.call(this, method, rewrittenUrl, ...args);
199
199
  }
package/src/index.ts CHANGED
@@ -42,21 +42,16 @@ export type {
42
42
  ReportResult,
43
43
  ReportToDaemonOptions,
44
44
  } from './utils/DaemonClient';
45
- export {
46
- getDefaultDaemonEndpoint,
47
- reportDebugDeviceToDaemon,
48
- checkDaemonConnection,
49
- startStreaming,
50
- stopStreaming,
51
- isStreaming,
52
- } from './utils/DaemonClient';
45
+ export { getDefaultDaemonEndpoint } from './utils/DaemonClient';
53
46
 
54
47
  // Types
55
48
  export type {
56
49
  AnyDebugFeature,
57
50
  BuiltInFeatureName,
58
51
  DebugFeature,
52
+ DebugFeatureListener,
59
53
  DebugFeatureRenderProps,
54
+ FeatureDataProvider,
60
55
  NetworkLogEntry,
61
56
  ConsoleLogEntry,
62
57
  ZustandLogEntry,
@@ -19,6 +19,12 @@ export interface DebugFeatureRenderProps<TSnapshot = unknown> {
19
19
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
20
  export type AnyDebugFeature = DebugFeature<any>;
21
21
 
22
+ /** Provides feature list and change notifications to consumers (e.g., DaemonClient). */
23
+ export interface FeatureDataProvider {
24
+ readonly features: AnyDebugFeature[];
25
+ subscribe(listener: DebugFeatureListener): () => void;
26
+ }
27
+
22
28
  export interface DebugFeature<TSnapshot = unknown> {
23
29
  name: string;
24
30
  label: string;
@@ -4,6 +4,7 @@ export type {
4
4
  DebugFeature,
5
5
  DebugFeatureListener,
6
6
  DebugFeatureRenderProps,
7
+ FeatureDataProvider,
7
8
  } from './feature';
8
9
 
9
10
  export type {