react-native-debug-toolkit 3.3.4 → 3.5.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 (258) hide show
  1. package/README.md +48 -46
  2. package/README.zh-CN.md +48 -46
  3. package/android/src/main/java/com/reactnativedebugtoolkit/DebugToolkitDevConnectModule.java +0 -187
  4. package/bin/debug-toolkit.js +0 -16
  5. package/ios/DebugToolkitDevConnect.h +0 -12
  6. package/ios/DebugToolkitDevConnect.mm +0 -321
  7. package/lib/commonjs/constants/logLevels.js +19 -0
  8. package/lib/commonjs/constants/logLevels.js.map +1 -0
  9. package/lib/commonjs/core/initialize.js +36 -18
  10. package/lib/commonjs/core/initialize.js.map +1 -1
  11. package/lib/commonjs/features/console/ConsoleLogTab.js +4 -15
  12. package/lib/commonjs/features/console/ConsoleLogTab.js.map +1 -1
  13. package/lib/commonjs/features/console/index.js +15 -8
  14. package/lib/commonjs/features/console/index.js.map +1 -1
  15. package/lib/commonjs/features/devConnect/DevConnectTab.js +18 -470
  16. package/lib/commonjs/features/devConnect/DevConnectTab.js.map +1 -1
  17. package/lib/commonjs/features/devConnect/devConnectPreferences.js +0 -12
  18. package/lib/commonjs/features/devConnect/devConnectPreferences.js.map +1 -1
  19. package/lib/commonjs/features/devConnect/devConnectUtils.js +2 -57
  20. package/lib/commonjs/features/devConnect/devConnectUtils.js.map +1 -1
  21. package/lib/commonjs/features/devConnect/index.js +1 -23
  22. package/lib/commonjs/features/devConnect/index.js.map +1 -1
  23. package/lib/commonjs/features/devConnect/nativeDevConnect.js +1 -103
  24. package/lib/commonjs/features/devConnect/nativeDevConnect.js.map +1 -1
  25. package/lib/commonjs/features/network/NetworkLogTab.js +91 -93
  26. package/lib/commonjs/features/network/NetworkLogTab.js.map +1 -1
  27. package/lib/commonjs/features/network/index.js +7 -4
  28. package/lib/commonjs/features/network/index.js.map +1 -1
  29. package/lib/commonjs/features/sessionHistory/SessionHistoryTab.js +1044 -0
  30. package/lib/commonjs/features/sessionHistory/SessionHistoryTab.js.map +1 -0
  31. package/lib/commonjs/features/sessionHistory/index.js +103 -0
  32. package/lib/commonjs/features/sessionHistory/index.js.map +1 -0
  33. package/lib/commonjs/features/track/index.js +4 -3
  34. package/lib/commonjs/features/track/index.js.map +1 -1
  35. package/lib/commonjs/index.js +27 -0
  36. package/lib/commonjs/index.js.map +1 -1
  37. package/lib/commonjs/ui/DebugView.js +3 -0
  38. package/lib/commonjs/ui/DebugView.js.map +1 -1
  39. package/lib/commonjs/ui/panel/DebugPanel.js +67 -34
  40. package/lib/commonjs/ui/panel/DebugPanel.js.map +1 -1
  41. package/lib/commonjs/ui/panel/FeatureIntroCard.js +131 -0
  42. package/lib/commonjs/ui/panel/FeatureIntroCard.js.map +1 -0
  43. package/lib/commonjs/ui/panel/FeatureRail.js +163 -0
  44. package/lib/commonjs/ui/panel/FeatureRail.js.map +1 -0
  45. package/lib/commonjs/ui/panel/FloatPanelView.js +169 -32
  46. package/lib/commonjs/ui/panel/FloatPanelView.js.map +1 -1
  47. package/lib/commonjs/ui/panel/buildFeatureSummary.js +207 -0
  48. package/lib/commonjs/ui/panel/buildFeatureSummary.js.map +1 -0
  49. package/lib/commonjs/ui/panel/filterFeatureSnapshot.js +43 -0
  50. package/lib/commonjs/ui/panel/filterFeatureSnapshot.js.map +1 -0
  51. package/lib/commonjs/ui/panel/tabPersistence.js +17 -0
  52. package/lib/commonjs/ui/panel/tabPersistence.js.map +1 -0
  53. package/lib/commonjs/ui/theme/colors.js +6 -0
  54. package/lib/commonjs/ui/theme/colors.js.map +1 -1
  55. package/lib/commonjs/utils/DaemonClient.js +30 -8
  56. package/lib/commonjs/utils/DaemonClient.js.map +1 -1
  57. package/lib/commonjs/utils/SessionManager.js +132 -0
  58. package/lib/commonjs/utils/SessionManager.js.map +1 -0
  59. package/lib/commonjs/utils/StorageAdapter.js +104 -0
  60. package/lib/commonjs/utils/StorageAdapter.js.map +1 -0
  61. package/lib/commonjs/utils/createChannelFeature.js +22 -5
  62. package/lib/commonjs/utils/createChannelFeature.js.map +1 -1
  63. package/lib/commonjs/utils/createDebugTab.js +21 -0
  64. package/lib/commonjs/utils/createDebugTab.js.map +1 -0
  65. package/lib/commonjs/utils/createPersistedObservableStore.js +14 -8
  66. package/lib/commonjs/utils/createPersistedObservableStore.js.map +1 -1
  67. package/lib/commonjs/utils/debugPreferences.js +28 -6
  68. package/lib/commonjs/utils/debugPreferences.js.map +1 -1
  69. package/lib/commonjs/utils/deviceReport.js +5 -1
  70. package/lib/commonjs/utils/deviceReport.js.map +1 -1
  71. package/lib/commonjs/utils/logRuntime.js +32 -0
  72. package/lib/commonjs/utils/logRuntime.js.map +1 -0
  73. package/lib/module/constants/logLevels.js +15 -0
  74. package/lib/module/constants/logLevels.js.map +1 -0
  75. package/lib/module/core/initialize.js +36 -18
  76. package/lib/module/core/initialize.js.map +1 -1
  77. package/lib/module/features/console/ConsoleLogTab.js +1 -12
  78. package/lib/module/features/console/ConsoleLogTab.js.map +1 -1
  79. package/lib/module/features/console/index.js +15 -8
  80. package/lib/module/features/console/index.js.map +1 -1
  81. package/lib/module/features/devConnect/DevConnectTab.js +21 -473
  82. package/lib/module/features/devConnect/DevConnectTab.js.map +1 -1
  83. package/lib/module/features/devConnect/devConnectPreferences.js +1 -12
  84. package/lib/module/features/devConnect/devConnectPreferences.js.map +1 -1
  85. package/lib/module/features/devConnect/devConnectUtils.js +1 -53
  86. package/lib/module/features/devConnect/devConnectUtils.js.map +1 -1
  87. package/lib/module/features/devConnect/index.js +5 -9
  88. package/lib/module/features/devConnect/index.js.map +1 -1
  89. package/lib/module/features/devConnect/nativeDevConnect.js +1 -100
  90. package/lib/module/features/devConnect/nativeDevConnect.js.map +1 -1
  91. package/lib/module/features/network/NetworkLogTab.js +91 -93
  92. package/lib/module/features/network/NetworkLogTab.js.map +1 -1
  93. package/lib/module/features/network/index.js +7 -4
  94. package/lib/module/features/network/index.js.map +1 -1
  95. package/lib/module/features/sessionHistory/SessionHistoryTab.js +1039 -0
  96. package/lib/module/features/sessionHistory/SessionHistoryTab.js.map +1 -0
  97. package/lib/module/features/sessionHistory/index.js +99 -0
  98. package/lib/module/features/sessionHistory/index.js.map +1 -0
  99. package/lib/module/features/track/index.js +4 -3
  100. package/lib/module/features/track/index.js.map +1 -1
  101. package/lib/module/index.js +4 -0
  102. package/lib/module/index.js.map +1 -1
  103. package/lib/module/ui/DebugView.js +3 -0
  104. package/lib/module/ui/DebugView.js.map +1 -1
  105. package/lib/module/ui/panel/DebugPanel.js +67 -34
  106. package/lib/module/ui/panel/DebugPanel.js.map +1 -1
  107. package/lib/module/ui/panel/FeatureIntroCard.js +126 -0
  108. package/lib/module/ui/panel/FeatureIntroCard.js.map +1 -0
  109. package/lib/module/ui/panel/FeatureRail.js +158 -0
  110. package/lib/module/ui/panel/FeatureRail.js.map +1 -0
  111. package/lib/module/ui/panel/FloatPanelView.js +170 -33
  112. package/lib/module/ui/panel/FloatPanelView.js.map +1 -1
  113. package/lib/module/ui/panel/buildFeatureSummary.js +203 -0
  114. package/lib/module/ui/panel/buildFeatureSummary.js.map +1 -0
  115. package/lib/module/ui/panel/filterFeatureSnapshot.js +39 -0
  116. package/lib/module/ui/panel/filterFeatureSnapshot.js.map +1 -0
  117. package/lib/module/ui/panel/tabPersistence.js +13 -0
  118. package/lib/module/ui/panel/tabPersistence.js.map +1 -0
  119. package/lib/module/ui/theme/colors.js +6 -0
  120. package/lib/module/ui/theme/colors.js.map +1 -1
  121. package/lib/module/utils/DaemonClient.js +30 -8
  122. package/lib/module/utils/DaemonClient.js.map +1 -1
  123. package/lib/module/utils/SessionManager.js +127 -0
  124. package/lib/module/utils/SessionManager.js.map +1 -0
  125. package/lib/module/utils/StorageAdapter.js +96 -0
  126. package/lib/module/utils/StorageAdapter.js.map +1 -0
  127. package/lib/module/utils/createChannelFeature.js +22 -5
  128. package/lib/module/utils/createChannelFeature.js.map +1 -1
  129. package/lib/module/utils/createDebugTab.js +17 -0
  130. package/lib/module/utils/createDebugTab.js.map +1 -0
  131. package/lib/module/utils/createPersistedObservableStore.js +14 -8
  132. package/lib/module/utils/createPersistedObservableStore.js.map +1 -1
  133. package/lib/module/utils/debugPreferences.js +27 -6
  134. package/lib/module/utils/debugPreferences.js.map +1 -1
  135. package/lib/module/utils/deviceReport.js +4 -1
  136. package/lib/module/utils/deviceReport.js.map +1 -1
  137. package/lib/module/utils/logRuntime.js +26 -0
  138. package/lib/module/utils/logRuntime.js.map +1 -0
  139. package/lib/typescript/src/constants/logLevels.d.ts +3 -0
  140. package/lib/typescript/src/constants/logLevels.d.ts.map +1 -0
  141. package/lib/typescript/src/core/initialize.d.ts +6 -0
  142. package/lib/typescript/src/core/initialize.d.ts.map +1 -1
  143. package/lib/typescript/src/features/console/ConsoleLogTab.d.ts.map +1 -1
  144. package/lib/typescript/src/features/console/index.d.ts +2 -1
  145. package/lib/typescript/src/features/console/index.d.ts.map +1 -1
  146. package/lib/typescript/src/features/devConnect/DevConnectTab.d.ts.map +1 -1
  147. package/lib/typescript/src/features/devConnect/devConnectPreferences.d.ts +0 -2
  148. package/lib/typescript/src/features/devConnect/devConnectPreferences.d.ts.map +1 -1
  149. package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts +0 -20
  150. package/lib/typescript/src/features/devConnect/devConnectUtils.d.ts.map +1 -1
  151. package/lib/typescript/src/features/devConnect/index.d.ts +2 -2
  152. package/lib/typescript/src/features/devConnect/index.d.ts.map +1 -1
  153. package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts +0 -25
  154. package/lib/typescript/src/features/devConnect/nativeDevConnect.d.ts.map +1 -1
  155. package/lib/typescript/src/features/devConnect/types.d.ts +1 -3
  156. package/lib/typescript/src/features/devConnect/types.d.ts.map +1 -1
  157. package/lib/typescript/src/features/network/NetworkLogTab.d.ts.map +1 -1
  158. package/lib/typescript/src/features/network/index.d.ts +2 -1
  159. package/lib/typescript/src/features/network/index.d.ts.map +1 -1
  160. package/lib/typescript/src/features/sessionHistory/SessionHistoryTab.d.ts +20 -0
  161. package/lib/typescript/src/features/sessionHistory/SessionHistoryTab.d.ts.map +1 -0
  162. package/lib/typescript/src/features/sessionHistory/index.d.ts +4 -0
  163. package/lib/typescript/src/features/sessionHistory/index.d.ts.map +1 -0
  164. package/lib/typescript/src/features/track/index.d.ts +2 -1
  165. package/lib/typescript/src/features/track/index.d.ts.map +1 -1
  166. package/lib/typescript/src/index.d.ts +6 -0
  167. package/lib/typescript/src/index.d.ts.map +1 -1
  168. package/lib/typescript/src/types/feature.d.ts +1 -1
  169. package/lib/typescript/src/types/feature.d.ts.map +1 -1
  170. package/lib/typescript/src/types/index.d.ts +2 -0
  171. package/lib/typescript/src/types/index.d.ts.map +1 -1
  172. package/lib/typescript/src/ui/DebugView.d.ts +4 -2
  173. package/lib/typescript/src/ui/DebugView.d.ts.map +1 -1
  174. package/lib/typescript/src/ui/panel/DebugPanel.d.ts +3 -1
  175. package/lib/typescript/src/ui/panel/DebugPanel.d.ts.map +1 -1
  176. package/lib/typescript/src/ui/panel/FeatureIntroCard.d.ts +11 -0
  177. package/lib/typescript/src/ui/panel/FeatureIntroCard.d.ts.map +1 -0
  178. package/lib/typescript/src/ui/panel/FeatureRail.d.ts +16 -0
  179. package/lib/typescript/src/ui/panel/FeatureRail.d.ts.map +1 -0
  180. package/lib/typescript/src/ui/panel/FloatPanelView.d.ts.map +1 -1
  181. package/lib/typescript/src/ui/panel/buildFeatureSummary.d.ts +13 -0
  182. package/lib/typescript/src/ui/panel/buildFeatureSummary.d.ts.map +1 -0
  183. package/lib/typescript/src/ui/panel/filterFeatureSnapshot.d.ts +3 -0
  184. package/lib/typescript/src/ui/panel/filterFeatureSnapshot.d.ts.map +1 -0
  185. package/lib/typescript/src/ui/panel/tabPersistence.d.ts +3 -0
  186. package/lib/typescript/src/ui/panel/tabPersistence.d.ts.map +1 -0
  187. package/lib/typescript/src/ui/theme/colors.d.ts +5 -0
  188. package/lib/typescript/src/ui/theme/colors.d.ts.map +1 -1
  189. package/lib/typescript/src/utils/DaemonClient.d.ts +7 -1
  190. package/lib/typescript/src/utils/DaemonClient.d.ts.map +1 -1
  191. package/lib/typescript/src/utils/SessionManager.d.ts +30 -0
  192. package/lib/typescript/src/utils/SessionManager.d.ts.map +1 -0
  193. package/lib/typescript/src/utils/StorageAdapter.d.ts +38 -0
  194. package/lib/typescript/src/utils/StorageAdapter.d.ts.map +1 -0
  195. package/lib/typescript/src/utils/createChannelFeature.d.ts +2 -0
  196. package/lib/typescript/src/utils/createChannelFeature.d.ts.map +1 -1
  197. package/lib/typescript/src/utils/createDebugTab.d.ts +18 -0
  198. package/lib/typescript/src/utils/createDebugTab.d.ts.map +1 -0
  199. package/lib/typescript/src/utils/createPersistedObservableStore.d.ts +4 -1
  200. package/lib/typescript/src/utils/createPersistedObservableStore.d.ts.map +1 -1
  201. package/lib/typescript/src/utils/debugPreferences.d.ts +1 -4
  202. package/lib/typescript/src/utils/debugPreferences.d.ts.map +1 -1
  203. package/lib/typescript/src/utils/deviceReport.d.ts +1 -0
  204. package/lib/typescript/src/utils/deviceReport.d.ts.map +1 -1
  205. package/lib/typescript/src/utils/logRuntime.d.ts +13 -0
  206. package/lib/typescript/src/utils/logRuntime.d.ts.map +1 -0
  207. package/package.json +10 -6
  208. package/src/constants/logLevels.ts +13 -0
  209. package/src/core/initialize.ts +61 -21
  210. package/src/features/console/ConsoleLogTab.tsx +1 -14
  211. package/src/features/console/index.ts +18 -8
  212. package/src/features/devConnect/DevConnectTab.tsx +17 -381
  213. package/src/features/devConnect/devConnectPreferences.ts +0 -15
  214. package/src/features/devConnect/devConnectUtils.ts +1 -81
  215. package/src/features/devConnect/index.ts +2 -9
  216. package/src/features/devConnect/nativeDevConnect.ts +1 -136
  217. package/src/features/devConnect/types.ts +1 -3
  218. package/src/features/network/NetworkLogTab.tsx +61 -71
  219. package/src/features/network/index.ts +12 -3
  220. package/src/features/sessionHistory/SessionHistoryTab.tsx +691 -0
  221. package/src/features/sessionHistory/index.ts +102 -0
  222. package/src/features/track/index.ts +10 -3
  223. package/src/index.ts +13 -0
  224. package/src/types/feature.ts +2 -1
  225. package/src/types/index.ts +10 -0
  226. package/src/ui/DebugView.tsx +6 -1
  227. package/src/ui/panel/DebugPanel.tsx +60 -30
  228. package/src/ui/panel/FeatureIntroCard.tsx +127 -0
  229. package/src/ui/panel/FeatureRail.tsx +165 -0
  230. package/src/ui/panel/FloatPanelView.tsx +176 -25
  231. package/src/ui/panel/buildFeatureSummary.ts +288 -0
  232. package/src/ui/panel/filterFeatureSnapshot.ts +51 -0
  233. package/src/ui/panel/tabPersistence.ts +22 -0
  234. package/src/ui/theme/colors.ts +7 -0
  235. package/src/utils/DaemonClient.ts +33 -5
  236. package/src/utils/SessionManager.ts +174 -0
  237. package/src/utils/StorageAdapter.ts +135 -0
  238. package/src/utils/createChannelFeature.ts +28 -6
  239. package/src/utils/createDebugTab.ts +32 -0
  240. package/src/utils/createPersistedObservableStore.ts +18 -10
  241. package/src/utils/debugPreferences.ts +38 -8
  242. package/src/utils/deviceReport.ts +5 -1
  243. package/src/utils/logRuntime.ts +39 -0
  244. package/app.plugin.js +0 -51
  245. package/dev-client.js +0 -3
  246. package/lib/commonjs/ui/panel/FeatureTabBar.js +0 -182
  247. package/lib/commonjs/ui/panel/FeatureTabBar.js.map +0 -1
  248. package/lib/module/ui/panel/FeatureTabBar.js +0 -177
  249. package/lib/module/ui/panel/FeatureTabBar.js.map +0 -1
  250. package/lib/typescript/src/ui/panel/FeatureTabBar.d.ts +0 -13
  251. package/lib/typescript/src/ui/panel/FeatureTabBar.d.ts.map +0 -1
  252. package/scripts/bundle/android.js +0 -101
  253. package/scripts/bundle/cli.js +0 -57
  254. package/scripts/bundle/doctor.js +0 -38
  255. package/scripts/bundle/ios.js +0 -179
  256. package/scripts/bundle/setup.js +0 -39
  257. package/scripts/debug-bundle.gradle +0 -147
  258. package/src/ui/panel/FeatureTabBar.tsx +0 -204
package/README.md CHANGED
@@ -63,8 +63,8 @@ Run the app in dev mode, then tap `DBG`.
63
63
  Start the desktop daemon:
64
64
 
65
65
  ```bash
66
- npm exec debug-toolkit --daemon-only
67
- # or: npx debug-toolkit --daemon-only
66
+ npm exec -- debug-toolkit --daemon-only
67
+ # or: npx react-native-debug-toolkit --daemon-only
68
68
  ```
69
69
 
70
70
  Open the Web Console:
@@ -77,45 +77,6 @@ In the app, open Debug Panel -> `DevConnect` -> `Send Once` or `Start Live Sync`
77
77
 
78
78
  DevConnect auto-detects simulator/emulator and uses local host settings automatically. On real devices, enter your computer IP to connect.
79
79
 
80
- ### Embedded Debug Bundle
81
-
82
- Debug builds need an embedded JS bundle for cold start when Metro is off.
83
-
84
- Bare React Native:
85
-
86
- ```bash
87
- npx debug-toolkit setup-bundle
88
- git diff
89
- git commit -am "chore: enable debug bundle embedding"
90
- ```
91
-
92
- Expo dev-client:
93
-
94
- ```json
95
- {
96
- "expo": {
97
- "plugins": [
98
- ["react-native-debug-toolkit/dev-client", { "embedBundle": true }]
99
- ]
100
- }
101
- }
102
- ```
103
-
104
- Verify built artifacts:
105
-
106
- ```bash
107
- npx debug-toolkit doctor-bundle --platform ios --app path/to/App.app
108
- npx debug-toolkit doctor-bundle --platform android --apk path/to/app-debug.apk
109
- ```
110
-
111
- After setup, build machines run normal Xcode, Gradle, React Native, or EAS commands. Do not run a separate mutation command on every build.
112
-
113
- For Remote JS Bundle, run Metro on your computer, enter computer IP and Metro port in `DevConnect`, then tap `Use Metro Bundle`. DevConnect persists the host and hot-reloads from Metro. Use **Reset** to go back to the embedded bundle.
114
-
115
- > **Debug builds only.** Metro host switching works in Debug builds. Release builds load the embedded bundle and the controls are disabled (`release: disabled` badge).
116
-
117
- **iOS — no AppDelegate changes required.** On install, DevConnect hooks `RCTBundleURLProvider` so the app **cold-starts from the embedded `main.jsbundle`** and only connects to Metro after you apply a host in the panel (fixes Expo `.expo/.virtual-metro-entry` red screens when Metro is off).
118
-
119
80
  The IP and ports are persisted through AsyncStorage when installed, or through the native module after rebuild.
120
81
 
121
82
  QR scan is optional. Install `react-native-camera-kit` or `expo-camera` in the app to enable the scan button. The app must request camera permission before scanning.
@@ -145,9 +106,9 @@ The daemon stores logs at:
145
106
  Custom store path:
146
107
 
147
108
  ```bash
148
- npm exec debug-toolkit --daemon-only --store /path/to/devices.json
149
- # or: npx debug-toolkit --daemon-only --store /path/to/devices.json
150
- DEBUG_TOOLKIT_DAEMON_STORE=/path/to/devices.json npm exec debug-toolkit --daemon-only
109
+ npm exec -- debug-toolkit --daemon-only --store /path/to/devices.json
110
+ # or: npx react-native-debug-toolkit --daemon-only --store /path/to/devices.json
111
+ DEBUG_TOOLKIT_DAEMON_STORE=/path/to/devices.json npm exec -- debug-toolkit --daemon-only
151
112
  ```
152
113
 
153
114
  ## Read Logs With HTTP
@@ -189,8 +150,8 @@ GET /console
189
150
  ## Use MCP
190
151
 
191
152
  ```bash
192
- claude mcp add debug-toolkit -- npm exec debug-toolkit
193
- # or: claude mcp add debug-toolkit -- npx debug-toolkit
153
+ claude mcp add debug-toolkit -- npm exec -- debug-toolkit
154
+ # or: claude mcp add debug-toolkit -- npx react-native-debug-toolkit
194
155
  ```
195
156
 
196
157
  Tools:
@@ -210,6 +171,46 @@ Disable features:
210
171
  </DebugView>
211
172
  ```
212
173
 
174
+ Custom tabs:
175
+
176
+ ```tsx
177
+ import {
178
+ DebugView,
179
+ createDebugTab,
180
+ type DebugFeatureRenderProps,
181
+ } from 'react-native-debug-toolkit';
182
+
183
+ type UserSnapshot = {
184
+ id?: string;
185
+ role?: string;
186
+ };
187
+
188
+ function UserDebugTab({ snapshot }: DebugFeatureRenderProps<UserSnapshot>) {
189
+ return (
190
+ <View>
191
+ <Text>User ID: {snapshot.id ?? '-'}</Text>
192
+ <Text>Role: {snapshot.role ?? '-'}</Text>
193
+ </View>
194
+ );
195
+ }
196
+
197
+ const userDebugTab = createDebugTab<UserSnapshot>({
198
+ name: 'user',
199
+ label: 'User',
200
+ getSnapshot: () => ({
201
+ id: authStore.user?.id,
202
+ role: authStore.user?.role,
203
+ }),
204
+ render: UserDebugTab,
205
+ });
206
+
207
+ <DebugView customFeatures={[userDebugTab]}>
208
+ <AppContent />
209
+ </DebugView>;
210
+ ```
211
+
212
+ Each custom feature becomes a panel tab. `name` is the stable tab id, `label` is shown in the tab bar, `getSnapshot` provides tab data, and `render` controls the UI. Add `subscribe` when the tab should refresh after external state changes.
213
+
213
214
  Navigation tracking:
214
215
 
215
216
  ```tsx
@@ -239,6 +240,7 @@ addTrackLog({ eventName: 'button_click' });
239
240
  - `DebugView`
240
241
  - `DebugToolkit`
241
242
  - `initializeDebugToolkit`
243
+ - `createDebugTab`
242
244
  - `createDebugDeviceReport`
243
245
  - `checkDaemonConnection`
244
246
  - `reportDebugDeviceToDaemon`
package/README.zh-CN.md CHANGED
@@ -63,8 +63,8 @@ export function App() {
63
63
  启动桌面 daemon:
64
64
 
65
65
  ```bash
66
- npm exec debug-toolkit --daemon-only
67
- # 或:npx debug-toolkit --daemon-only
66
+ npm exec -- debug-toolkit --daemon-only
67
+ # 或:npx react-native-debug-toolkit --daemon-only
68
68
  ```
69
69
 
70
70
  打开 Web Console:
@@ -77,45 +77,6 @@ App 内打开 Debug Panel -> `DevConnect` -> `Send Once` 或 `Start Live Sync`
77
77
 
78
78
  DevConnect 自动识别模拟器/真机,模拟器下自动使用本机 Metro/daemon 地址。真机需输入电脑 IP 地址。
79
79
 
80
- ### Debug 包内置 Bundle
81
-
82
- Debug 包要在 Metro 关闭时冷启动,必须内置 JS bundle。
83
-
84
- Bare React Native:
85
-
86
- ```bash
87
- npx debug-toolkit setup-bundle
88
- git diff
89
- git commit -am "chore: enable debug bundle embedding"
90
- ```
91
-
92
- Expo dev-client:
93
-
94
- ```json
95
- {
96
- "expo": {
97
- "plugins": [
98
- ["react-native-debug-toolkit/dev-client", { "embedBundle": true }]
99
- ]
100
- }
101
- }
102
- ```
103
-
104
- 验证产物:
105
-
106
- ```bash
107
- npx debug-toolkit doctor-bundle --platform ios --app path/to/App.app
108
- npx debug-toolkit doctor-bundle --platform android --apk path/to/app-debug.apk
109
- ```
110
-
111
- setup 后配置进仓库,打包机继续跑正常 Xcode、Gradle、React Native 或 EAS 命令。不要每次打包再跑额外修改命令。
112
-
113
- Remote JS Bundle:先在电脑启动 Metro,在 `DevConnect` 输入电脑 IP 和 Metro 端口,然后点 `Use Metro Bundle`。DevConnect 会持久化 host 并从 Metro 热重载。点 **Reset** 可回到内置 bundle。
114
-
115
- > **仅 Debug 包可用。** Release 包控件会显示 `release: disabled` 并禁用。
116
-
117
- **iOS — 无需改 AppDelegate。** 安装本库后会 hook `RCTBundleURLProvider`:**未配置 IP 时冷启动走内置 `main.jsbundle`**,只有在面板里应用 host 后才连 Metro(可避免 Metro 未开时的 `.expo/.virtual-metro-entry` 红屏)。
118
-
119
80
  IP 和端口会通过 AsyncStorage 持久化;如果没装 AsyncStorage,则在重建后通过本库原生模块持久化。
120
81
 
121
82
  扫码是可选能力。App 安装 `react-native-camera-kit` 或 `expo-camera` 后,DevConnect 才显示扫码按钮。App 仍需自己配置相机权限文案,并在使用扫码前申请相机权限。
@@ -145,9 +106,9 @@ daemon 默认日志文件:
145
106
  自定义存储路径:
146
107
 
147
108
  ```bash
148
- npm exec debug-toolkit --daemon-only --store /path/to/devices.json
149
- # 或:npx debug-toolkit --daemon-only --store /path/to/devices.json
150
- DEBUG_TOOLKIT_DAEMON_STORE=/path/to/devices.json npm exec debug-toolkit --daemon-only
109
+ npm exec -- debug-toolkit --daemon-only --store /path/to/devices.json
110
+ # 或:npx react-native-debug-toolkit --daemon-only --store /path/to/devices.json
111
+ DEBUG_TOOLKIT_DAEMON_STORE=/path/to/devices.json npm exec -- debug-toolkit --daemon-only
151
112
  ```
152
113
 
153
114
  ## 用 HTTP 读取日志
@@ -189,8 +150,8 @@ GET /console
189
150
  ## 使用 MCP
190
151
 
191
152
  ```bash
192
- claude mcp add debug-toolkit -- npm exec debug-toolkit
193
- # 或:claude mcp add debug-toolkit -- npx debug-toolkit
153
+ claude mcp add debug-toolkit -- npm exec -- debug-toolkit
154
+ # 或:claude mcp add debug-toolkit -- npx react-native-debug-toolkit
194
155
  ```
195
156
 
196
157
  工具:
@@ -210,6 +171,46 @@ claude mcp add debug-toolkit -- npm exec debug-toolkit
210
171
  </DebugView>
211
172
  ```
212
173
 
174
+ 自定义 Tab:
175
+
176
+ ```tsx
177
+ import {
178
+ DebugView,
179
+ createDebugTab,
180
+ type DebugFeatureRenderProps,
181
+ } from 'react-native-debug-toolkit';
182
+
183
+ type UserSnapshot = {
184
+ id?: string;
185
+ role?: string;
186
+ };
187
+
188
+ function UserDebugTab({ snapshot }: DebugFeatureRenderProps<UserSnapshot>) {
189
+ return (
190
+ <View>
191
+ <Text>User ID: {snapshot.id ?? '-'}</Text>
192
+ <Text>Role: {snapshot.role ?? '-'}</Text>
193
+ </View>
194
+ );
195
+ }
196
+
197
+ const userDebugTab = createDebugTab<UserSnapshot>({
198
+ name: 'user',
199
+ label: 'User',
200
+ getSnapshot: () => ({
201
+ id: authStore.user?.id,
202
+ role: authStore.user?.role,
203
+ }),
204
+ render: UserDebugTab,
205
+ });
206
+
207
+ <DebugView customFeatures={[userDebugTab]}>
208
+ <AppContent />
209
+ </DebugView>;
210
+ ```
211
+
212
+ 每个自定义 feature 都会变成一个面板 Tab。`name` 是稳定 Tab id,`label` 显示在 Tab 栏,`getSnapshot` 提供展示数据,`render` 控制展示 UI。外部状态变化后需要自动刷新时,给它加 `subscribe`。
213
+
213
214
  导航追踪:
214
215
 
215
216
  ```tsx
@@ -239,6 +240,7 @@ addTrackLog({ eventName: 'button_click' });
239
240
  - `DebugView`
240
241
  - `DebugToolkit`
241
242
  - `initializeDebugToolkit`
243
+ - `createDebugTab`
242
244
  - `createDebugDeviceReport`
243
245
  - `checkDaemonConnection`
244
246
  - `reportDebugDeviceToDaemon`
@@ -8,16 +8,11 @@ import androidx.annotation.NonNull;
8
8
  import androidx.annotation.Nullable;
9
9
 
10
10
  import com.reactnativedebugtoolkit.BuildConfig;
11
- import com.facebook.react.bridge.Arguments;
12
11
  import com.facebook.react.bridge.Promise;
13
12
  import com.facebook.react.bridge.ReactApplicationContext;
14
13
  import com.facebook.react.bridge.ReactContextBaseJavaModule;
15
14
  import com.facebook.react.bridge.ReactMethod;
16
- import com.facebook.react.bridge.UiThreadUtil;
17
- import com.facebook.react.bridge.WritableMap;
18
15
 
19
- import java.lang.reflect.Method;
20
- import java.lang.reflect.Proxy;
21
16
  import java.net.Inet4Address;
22
17
  import java.net.InetAddress;
23
18
  import java.net.NetworkInterface;
@@ -25,11 +20,6 @@ import java.util.Enumeration;
25
20
 
26
21
  public class DebugToolkitDevConnectModule extends ReactContextBaseJavaModule {
27
22
  private static final String MODULE_NAME = "DebugToolkitDevConnect";
28
- private static final String BUNDLE_ROOT = "index";
29
- private static final String DEBUG_SERVER_HOST_KEY = "debug_http_host";
30
- private static final String KOTLIN_FUNCTION1_CLASS = "kotlin.jvm.functions.Function1";
31
- private static final String APPLY_RELOAD_REASON = "DebugToolkit DevConnect Metro host changed";
32
- private static final String RESET_RELOAD_REASON = "DebugToolkit DevConnect Metro host reset";
33
23
 
34
24
  public DebugToolkitDevConnectModule(ReactApplicationContext reactContext) {
35
25
  super(reactContext);
@@ -45,183 +35,6 @@ public class DebugToolkitDevConnectModule extends ReactContextBaseJavaModule {
45
35
  return PreferenceManager.getDefaultSharedPreferences(getReactApplicationContext());
46
36
  }
47
37
 
48
- @Nullable
49
- private Object callGetter(Object target, String methodName) {
50
- try {
51
- Method method = target.getClass().getMethod(methodName);
52
- return method.invoke(target);
53
- } catch (Exception ignored) {
54
- return null;
55
- }
56
- }
57
-
58
- private void setDebugServerHost(@Nullable Object devSupportManager, String hostPort) throws Exception {
59
- if (devSupportManager == null) {
60
- return;
61
- }
62
-
63
- Object devSettings = callGetter(devSupportManager, "getDevSettings");
64
- Object packagerConnectionSettings = devSettings == null
65
- ? null
66
- : callGetter(devSettings, "getPackagerConnectionSettings");
67
- if (packagerConnectionSettings == null) {
68
- return;
69
- }
70
-
71
- Method setter = packagerConnectionSettings.getClass().getMethod("setDebugServerHost", String.class);
72
- setter.invoke(packagerConnectionSettings, hostPort);
73
- }
74
-
75
- private boolean setReactHostBundleSource(Object reactHost, String hostPort) throws Exception {
76
- if (hostPort.length() == 0) {
77
- return false;
78
- }
79
-
80
- try {
81
- Class<?> function1Class = Class.forName(KOTLIN_FUNCTION1_CLASS);
82
- Method setBundleSourceMethod = reactHost.getClass().getMethod(
83
- "setBundleSource",
84
- String.class,
85
- String.class,
86
- function1Class
87
- );
88
- Object queryMapper = Proxy.newProxyInstance(
89
- function1Class.getClassLoader(),
90
- new Class<?>[] { function1Class },
91
- (proxy, method, args) -> {
92
- String methodName = method.getName();
93
- if ("invoke".equals(methodName)) {
94
- return args != null && args.length > 0 ? args[0] : null;
95
- }
96
- if ("toString".equals(methodName)) {
97
- return "DebugToolkitIdentityQueryMapper";
98
- }
99
- if ("hashCode".equals(methodName)) {
100
- return System.identityHashCode(proxy);
101
- }
102
- if ("equals".equals(methodName)) {
103
- return proxy == (args != null && args.length > 0 ? args[0] : null);
104
- }
105
- return null;
106
- }
107
- );
108
- setBundleSourceMethod.invoke(reactHost, hostPort, BUNDLE_ROOT, queryMapper);
109
- return true;
110
- } catch (ClassNotFoundException | NoSuchMethodException ignored) {
111
- return false;
112
- }
113
- }
114
-
115
- private boolean triggerDevSupportReload(
116
- @Nullable Object devSupportManager,
117
- String hostPort
118
- ) throws Exception {
119
- if (devSupportManager == null) {
120
- return false;
121
- }
122
-
123
- Object enabled = callGetter(devSupportManager, "getDevSupportEnabled");
124
- if (enabled instanceof Boolean && !((Boolean) enabled)) {
125
- return false;
126
- }
127
-
128
- setDebugServerHost(devSupportManager, hostPort);
129
- Method reloadMethod = devSupportManager.getClass().getMethod("handleReloadJS");
130
- reloadMethod.invoke(devSupportManager);
131
- return true;
132
- }
133
-
134
- private boolean reloadFromReactHost(
135
- Context applicationContext,
136
- String reason,
137
- String hostPort
138
- ) throws Exception {
139
- Object reactHost = callGetter(applicationContext, "getReactHost");
140
- if (reactHost == null) {
141
- return false;
142
- }
143
-
144
- if (setReactHostBundleSource(reactHost, hostPort)) {
145
- return true;
146
- }
147
-
148
- if (triggerDevSupportReload(callGetter(reactHost, "getDevSupportManager"), hostPort)) {
149
- return true;
150
- }
151
-
152
- Method reloadMethod = reactHost.getClass().getMethod("reload", String.class);
153
- reloadMethod.invoke(reactHost, reason);
154
- return true;
155
- }
156
-
157
- private boolean reloadFromReactNativeHost(Context applicationContext, String hostPort) throws Exception {
158
- Object reactNativeHost = callGetter(applicationContext, "getReactNativeHost");
159
- Object instanceManager = reactNativeHost == null
160
- ? null
161
- : callGetter(reactNativeHost, "getReactInstanceManager");
162
- Object devSupportManager = instanceManager == null
163
- ? null
164
- : callGetter(instanceManager, "getDevSupportManager");
165
- return triggerDevSupportReload(devSupportManager, hostPort);
166
- }
167
-
168
- private void resolveAfterReload(
169
- String reason,
170
- @Nullable WritableMap result,
171
- String hostPort,
172
- Promise promise
173
- ) {
174
- UiThreadUtil.runOnUiThread(() -> {
175
- try {
176
- Context applicationContext = getReactApplicationContext().getApplicationContext();
177
- boolean reloaded = reloadFromReactHost(applicationContext, reason, hostPort)
178
- || reloadFromReactNativeHost(applicationContext, hostPort);
179
- if (!reloaded) {
180
- promise.reject("reload_unavailable", "Unable to trigger React Native reload after updating Metro host.");
181
- return;
182
- }
183
- promise.resolve(result);
184
- } catch (Exception error) {
185
- promise.reject("reload_failed", "Unable to trigger React Native reload after updating Metro host.", error);
186
- }
187
- });
188
- }
189
-
190
- @ReactMethod
191
- public void getMetroHost(Promise promise) {
192
- @Nullable String host = getPreferences().getString(DEBUG_SERVER_HOST_KEY, null);
193
- promise.resolve(host);
194
- }
195
-
196
- @ReactMethod
197
- public void applyMetroHost(String hostPort, Promise promise) {
198
- if (hostPort == null || hostPort.length() == 0) {
199
- promise.reject("invalid_host", "Metro host cannot be empty.");
200
- return;
201
- }
202
-
203
- boolean stored = getPreferences().edit().putString(DEBUG_SERVER_HOST_KEY, hostPort).commit();
204
- if (!stored) {
205
- promise.reject("storage_failed", "Unable to persist Metro host.");
206
- return;
207
- }
208
-
209
- WritableMap result = Arguments.createMap();
210
- result.putString("hostPort", hostPort);
211
- resolveAfterReload(APPLY_RELOAD_REASON, result, hostPort, promise);
212
- }
213
-
214
- @ReactMethod
215
- public void resetMetroHost(Promise promise) {
216
- boolean stored = getPreferences().edit().remove(DEBUG_SERVER_HOST_KEY).commit();
217
- if (!stored) {
218
- promise.reject("storage_failed", "Unable to reset Metro host.");
219
- return;
220
- }
221
-
222
- resolveAfterReload(RESET_RELOAD_REASON, null, "", promise);
223
- }
224
-
225
38
  @ReactMethod
226
39
  public void getPreference(String key, Promise promise) {
227
40
  @Nullable String value = getPreferences().getString(key, null);
@@ -27,16 +27,9 @@ function hasHelpFlag(args) {
27
27
  function printHelp() {
28
28
  process.stderr.write(
29
29
  'Usage: debug-toolkit [--host 0.0.0.0] [--port 3799] [--token dev-token] [--store ~/.react-native-debug-toolkit/daemon-devices.json] [--daemon-only]\n'
30
- + ' debug-toolkit setup-bundle [--platform ios|android] [--undo] [--check] [--ios-target <name>]\n'
31
- + ' debug-toolkit doctor-bundle --platform ios --app <path-to.app>\n'
32
- + ' debug-toolkit doctor-bundle --platform android --apk <path-to.apk>\n'
33
30
  + '\n'
34
31
  + 'Starts the debug toolkit: daemon (HTTP + Web Console) and MCP stdio server.\n'
35
32
  + '\n'
36
- + 'Commands:\n'
37
- + ' setup-bundle Persistently configure host app debug builds to embed JS bundle\n'
38
- + ' doctor-bundle Verify source config or built app package contains embedded bundle\n'
39
- + '\n'
40
33
  + 'Daemon options:\n'
41
34
  + ' --host <addr> Host to bind (default: 0.0.0.0)\n'
42
35
  + ' --port <port> Port to bind (default: 3799)\n'
@@ -64,15 +57,6 @@ async function main() {
64
57
  return;
65
58
  }
66
59
 
67
- if (['setup-bundle', 'doctor-bundle', 'embed'].includes(args[0])) {
68
- const { runBundleCli } = require('../scripts/bundle/cli');
69
- const code = await runBundleCli(args);
70
- if (code !== 0) {
71
- process.exitCode = code;
72
- }
73
- return;
74
- }
75
-
76
60
  const host = readOption(args, '--host', process.env.DEBUG_TOOLKIT_DAEMON_HOST || DEFAULT_HOST);
77
61
  const port = Number(readOption(args, '--port', process.env.DEBUG_TOOLKIT_DAEMON_PORT || DEFAULT_PORT));
78
62
  const token = readOption(args, '--token', process.env.DEBUG_TOOLKIT_DAEMON_TOKEN || '');
@@ -2,16 +2,4 @@
2
2
 
3
3
  NS_ASSUME_NONNULL_BEGIN
4
4
 
5
- /**
6
- Returns a Metro bundle URL when the user has applied a host via DevConnect; otherwise nil.
7
-
8
- Zero-config: installing this pod hooks RCTBundleURLProvider so cold start uses the embedded
9
- main.jsbundle until DevConnect applies a host. You do not need to change AppDelegate.
10
-
11
- Optional override for custom bundleURL() implementations:
12
-
13
- if let metro = DebugToolkitMetroBundleURL() { return metro }
14
- */
15
- FOUNDATION_EXPORT NSURL * _Nullable DebugToolkitMetroBundleURL(void);
16
-
17
5
  NS_ASSUME_NONNULL_END