react-native-debug-toolkit 0.6.4 → 2.0.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 (277) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -212
  3. package/lib/commonjs/components/ClipboardTab.js +92 -0
  4. package/lib/commonjs/components/ClipboardTab.js.map +1 -0
  5. package/lib/commonjs/components/ConsoleLogTab.js +295 -0
  6. package/lib/commonjs/components/ConsoleLogTab.js.map +1 -0
  7. package/lib/commonjs/components/EnvironmentTab.js +288 -0
  8. package/lib/commonjs/components/EnvironmentTab.js.map +1 -0
  9. package/lib/commonjs/components/FloatPanelView.js +797 -0
  10. package/lib/commonjs/components/FloatPanelView.js.map +1 -0
  11. package/lib/commonjs/components/NavigationLogTab.js +131 -0
  12. package/lib/commonjs/components/NavigationLogTab.js.map +1 -0
  13. package/lib/commonjs/components/NetworkLogTab.js +575 -0
  14. package/lib/commonjs/components/NetworkLogTab.js.map +1 -0
  15. package/lib/commonjs/components/ThirdPartyLibsTab.js +97 -0
  16. package/lib/commonjs/components/ThirdPartyLibsTab.js.map +1 -0
  17. package/lib/commonjs/components/TrackLogTab.js +372 -0
  18. package/lib/commonjs/components/TrackLogTab.js.map +1 -0
  19. package/lib/commonjs/components/ZustandLogTab.js +451 -0
  20. package/lib/commonjs/components/ZustandLogTab.js.map +1 -0
  21. package/lib/commonjs/components/shared/CollapsibleSection.js +84 -0
  22. package/lib/commonjs/components/shared/CollapsibleSection.js.map +1 -0
  23. package/lib/commonjs/components/shared/CopyButton.js +64 -0
  24. package/lib/commonjs/components/shared/CopyButton.js.map +1 -0
  25. package/lib/commonjs/components/shared/JsonView.js +157 -0
  26. package/lib/commonjs/components/shared/JsonView.js.map +1 -0
  27. package/lib/commonjs/core/DebugToolkit.js +142 -0
  28. package/lib/commonjs/core/DebugToolkit.js.map +1 -0
  29. package/lib/commonjs/core/DebugToolkitProvider.js +64 -0
  30. package/lib/commonjs/core/DebugToolkitProvider.js.map +1 -0
  31. package/lib/commonjs/features/ClipboardFeature.js +17 -0
  32. package/lib/commonjs/features/ClipboardFeature.js.map +1 -0
  33. package/lib/commonjs/features/ConsoleLogFeature.js +98 -0
  34. package/lib/commonjs/features/ConsoleLogFeature.js.map +1 -0
  35. package/lib/commonjs/features/EnvironmentFeature.js +168 -0
  36. package/lib/commonjs/features/EnvironmentFeature.js.map +1 -0
  37. package/lib/commonjs/features/NavigationLogFeature.js +60 -0
  38. package/lib/commonjs/features/NavigationLogFeature.js.map +1 -0
  39. package/lib/commonjs/features/NetworkFeature.js +328 -0
  40. package/lib/commonjs/features/NetworkFeature.js.map +1 -0
  41. package/lib/commonjs/features/ThirdPartyLibsFeature.js +51 -0
  42. package/lib/commonjs/features/ThirdPartyLibsFeature.js.map +1 -0
  43. package/lib/commonjs/features/TrackFeature.js +55 -0
  44. package/lib/commonjs/features/TrackFeature.js.map +1 -0
  45. package/lib/commonjs/features/ZustandLogFeature.js +76 -0
  46. package/lib/commonjs/features/ZustandLogFeature.js.map +1 -0
  47. package/lib/commonjs/hooks/useNavigationLogger.js +78 -0
  48. package/lib/commonjs/hooks/useNavigationLogger.js.map +1 -0
  49. package/lib/commonjs/hooks/useSlideDetailAnimation.js +53 -0
  50. package/lib/commonjs/hooks/useSlideDetailAnimation.js.map +1 -0
  51. package/lib/commonjs/index.js +165 -0
  52. package/lib/commonjs/index.js.map +1 -0
  53. package/lib/commonjs/initialize.js +161 -0
  54. package/lib/commonjs/initialize.js.map +1 -0
  55. package/lib/commonjs/native/NativeDebugLibs.js +58 -0
  56. package/lib/commonjs/native/NativeDebugLibs.js.map +1 -0
  57. package/lib/commonjs/package.json +1 -0
  58. package/lib/commonjs/types/index.js +6 -0
  59. package/lib/commonjs/types/index.js.map +1 -0
  60. package/lib/commonjs/utils/constants.js +135 -0
  61. package/lib/commonjs/utils/constants.js.map +1 -0
  62. package/lib/commonjs/utils/copyToComputer.js +97 -0
  63. package/lib/commonjs/utils/copyToComputer.js.map +1 -0
  64. package/lib/commonjs/utils/createEventChannel.js +21 -0
  65. package/lib/commonjs/utils/createEventChannel.js.map +1 -0
  66. package/lib/commonjs/utils/createObservableStore.js +38 -0
  67. package/lib/commonjs/utils/createObservableStore.js.map +1 -0
  68. package/lib/commonjs/utils/safeStringify.js +27 -0
  69. package/lib/commonjs/utils/safeStringify.js.map +1 -0
  70. package/lib/module/components/ClipboardTab.js +86 -0
  71. package/lib/module/components/ClipboardTab.js.map +1 -0
  72. package/lib/module/components/ConsoleLogTab.js +290 -0
  73. package/lib/module/components/ConsoleLogTab.js.map +1 -0
  74. package/lib/module/components/EnvironmentTab.js +282 -0
  75. package/lib/module/components/EnvironmentTab.js.map +1 -0
  76. package/lib/module/components/FloatPanelView.js +791 -0
  77. package/lib/module/components/FloatPanelView.js.map +1 -0
  78. package/lib/module/components/NavigationLogTab.js +126 -0
  79. package/lib/module/components/NavigationLogTab.js.map +1 -0
  80. package/lib/module/components/NetworkLogTab.js +570 -0
  81. package/lib/module/components/NetworkLogTab.js.map +1 -0
  82. package/lib/module/components/ThirdPartyLibsTab.js +91 -0
  83. package/lib/module/components/ThirdPartyLibsTab.js.map +1 -0
  84. package/lib/module/components/TrackLogTab.js +367 -0
  85. package/lib/module/components/TrackLogTab.js.map +1 -0
  86. package/lib/module/components/ZustandLogTab.js +446 -0
  87. package/lib/module/components/ZustandLogTab.js.map +1 -0
  88. package/lib/module/components/shared/CollapsibleSection.js +78 -0
  89. package/lib/module/components/shared/CollapsibleSection.js.map +1 -0
  90. package/lib/module/components/shared/CopyButton.js +58 -0
  91. package/lib/module/components/shared/CopyButton.js.map +1 -0
  92. package/lib/module/components/shared/JsonView.js +152 -0
  93. package/lib/module/components/shared/JsonView.js.map +1 -0
  94. package/lib/module/core/DebugToolkit.js +137 -0
  95. package/lib/module/core/DebugToolkit.js.map +1 -0
  96. package/lib/module/core/DebugToolkitProvider.js +58 -0
  97. package/lib/module/core/DebugToolkitProvider.js.map +1 -0
  98. package/lib/module/features/ClipboardFeature.js +12 -0
  99. package/lib/module/features/ClipboardFeature.js.map +1 -0
  100. package/lib/module/features/ConsoleLogFeature.js +93 -0
  101. package/lib/module/features/ConsoleLogFeature.js.map +1 -0
  102. package/lib/module/features/EnvironmentFeature.js +164 -0
  103. package/lib/module/features/EnvironmentFeature.js.map +1 -0
  104. package/lib/module/features/NavigationLogFeature.js +54 -0
  105. package/lib/module/features/NavigationLogFeature.js.map +1 -0
  106. package/lib/module/features/NetworkFeature.js +322 -0
  107. package/lib/module/features/NetworkFeature.js.map +1 -0
  108. package/lib/module/features/ThirdPartyLibsFeature.js +46 -0
  109. package/lib/module/features/ThirdPartyLibsFeature.js.map +1 -0
  110. package/lib/module/features/TrackFeature.js +49 -0
  111. package/lib/module/features/TrackFeature.js.map +1 -0
  112. package/lib/module/features/ZustandLogFeature.js +69 -0
  113. package/lib/module/features/ZustandLogFeature.js.map +1 -0
  114. package/lib/module/hooks/useNavigationLogger.js +74 -0
  115. package/lib/module/hooks/useNavigationLogger.js.map +1 -0
  116. package/lib/module/hooks/useSlideDetailAnimation.js +50 -0
  117. package/lib/module/hooks/useSlideDetailAnimation.js.map +1 -0
  118. package/lib/module/index.js +29 -0
  119. package/lib/module/index.js.map +1 -0
  120. package/lib/module/initialize.js +156 -0
  121. package/lib/module/initialize.js.map +1 -0
  122. package/lib/module/native/NativeDebugLibs.js +54 -0
  123. package/lib/module/native/NativeDebugLibs.js.map +1 -0
  124. package/lib/module/package.json +1 -0
  125. package/lib/module/types/index.js +4 -0
  126. package/lib/module/types/index.js.map +1 -0
  127. package/lib/module/utils/constants.js +130 -0
  128. package/lib/module/utils/constants.js.map +1 -0
  129. package/lib/module/utils/copyToComputer.js +91 -0
  130. package/lib/module/utils/copyToComputer.js.map +1 -0
  131. package/lib/module/utils/createEventChannel.js +17 -0
  132. package/lib/module/utils/createEventChannel.js.map +1 -0
  133. package/lib/module/utils/createObservableStore.js +34 -0
  134. package/lib/module/utils/createObservableStore.js.map +1 -0
  135. package/lib/module/utils/safeStringify.js +23 -0
  136. package/lib/module/utils/safeStringify.js.map +1 -0
  137. package/lib/typescript/src/components/ClipboardTab.d.ts +4 -0
  138. package/lib/typescript/src/components/ClipboardTab.d.ts.map +1 -0
  139. package/lib/typescript/src/components/ConsoleLogTab.d.ts +4 -0
  140. package/lib/typescript/src/components/ConsoleLogTab.d.ts.map +1 -0
  141. package/lib/typescript/src/components/EnvironmentTab.d.ts +4 -0
  142. package/lib/typescript/src/components/EnvironmentTab.d.ts.map +1 -0
  143. package/lib/typescript/src/components/FloatPanelView.d.ts +64 -0
  144. package/lib/typescript/src/components/FloatPanelView.d.ts.map +1 -0
  145. package/lib/typescript/src/components/NavigationLogTab.d.ts +4 -0
  146. package/lib/typescript/src/components/NavigationLogTab.d.ts.map +1 -0
  147. package/lib/typescript/src/components/NetworkLogTab.d.ts +4 -0
  148. package/lib/typescript/src/components/NetworkLogTab.d.ts.map +1 -0
  149. package/lib/typescript/src/components/ThirdPartyLibsTab.d.ts +4 -0
  150. package/lib/typescript/src/components/ThirdPartyLibsTab.d.ts.map +1 -0
  151. package/lib/typescript/src/components/TrackLogTab.d.ts +4 -0
  152. package/lib/typescript/src/components/TrackLogTab.d.ts.map +1 -0
  153. package/lib/typescript/src/components/ZustandLogTab.d.ts +4 -0
  154. package/lib/typescript/src/components/ZustandLogTab.d.ts.map +1 -0
  155. package/lib/typescript/src/components/shared/CollapsibleSection.d.ts +9 -0
  156. package/lib/typescript/src/components/shared/CollapsibleSection.d.ts.map +1 -0
  157. package/lib/typescript/src/components/shared/CopyButton.d.ts +12 -0
  158. package/lib/typescript/src/components/shared/CopyButton.d.ts.map +1 -0
  159. package/lib/typescript/src/components/shared/JsonView.d.ts +6 -0
  160. package/lib/typescript/src/components/shared/JsonView.d.ts.map +1 -0
  161. package/lib/typescript/src/core/DebugToolkit.d.ts +27 -0
  162. package/lib/typescript/src/core/DebugToolkit.d.ts.map +1 -0
  163. package/lib/typescript/src/core/DebugToolkitProvider.d.ts +18 -0
  164. package/lib/typescript/src/core/DebugToolkitProvider.d.ts.map +1 -0
  165. package/lib/typescript/src/features/ClipboardFeature.d.ts +3 -0
  166. package/lib/typescript/src/features/ClipboardFeature.d.ts.map +1 -0
  167. package/lib/typescript/src/features/ConsoleLogFeature.d.ts +7 -0
  168. package/lib/typescript/src/features/ConsoleLogFeature.d.ts.map +1 -0
  169. package/lib/typescript/src/features/EnvironmentFeature.d.ts +8 -0
  170. package/lib/typescript/src/features/EnvironmentFeature.d.ts.map +1 -0
  171. package/lib/typescript/src/features/NavigationLogFeature.d.ts +8 -0
  172. package/lib/typescript/src/features/NavigationLogFeature.d.ts.map +1 -0
  173. package/lib/typescript/src/features/NetworkFeature.d.ts +28 -0
  174. package/lib/typescript/src/features/NetworkFeature.d.ts.map +1 -0
  175. package/lib/typescript/src/features/ThirdPartyLibsFeature.d.ts +3 -0
  176. package/lib/typescript/src/features/ThirdPartyLibsFeature.d.ts.map +1 -0
  177. package/lib/typescript/src/features/TrackFeature.d.ts +12 -0
  178. package/lib/typescript/src/features/TrackFeature.d.ts.map +1 -0
  179. package/lib/typescript/src/features/ZustandLogFeature.d.ts +29 -0
  180. package/lib/typescript/src/features/ZustandLogFeature.d.ts.map +1 -0
  181. package/lib/typescript/src/hooks/useNavigationLogger.d.ts +20 -0
  182. package/lib/typescript/src/hooks/useNavigationLogger.d.ts.map +1 -0
  183. package/lib/typescript/src/hooks/useSlideDetailAnimation.d.ts +11 -0
  184. package/lib/typescript/src/hooks/useSlideDetailAnimation.d.ts.map +1 -0
  185. package/lib/typescript/src/index.d.ts +26 -0
  186. package/lib/typescript/src/index.d.ts.map +1 -0
  187. package/lib/typescript/src/initialize.d.ts +51 -0
  188. package/lib/typescript/src/initialize.d.ts.map +1 -0
  189. package/lib/typescript/src/native/NativeDebugLibs.d.ts +11 -0
  190. package/lib/typescript/src/native/NativeDebugLibs.d.ts.map +1 -0
  191. package/lib/typescript/src/types/index.d.ts +112 -0
  192. package/lib/typescript/src/types/index.d.ts.map +1 -0
  193. package/lib/typescript/src/utils/constants.d.ts +96 -0
  194. package/lib/typescript/src/utils/constants.d.ts.map +1 -0
  195. package/lib/typescript/src/utils/copyToComputer.d.ts +30 -0
  196. package/lib/typescript/src/utils/copyToComputer.d.ts.map +1 -0
  197. package/lib/typescript/src/utils/createEventChannel.d.ts +7 -0
  198. package/lib/typescript/src/utils/createEventChannel.d.ts.map +1 -0
  199. package/lib/typescript/src/utils/createObservableStore.d.ts +9 -0
  200. package/lib/typescript/src/utils/createObservableStore.d.ts.map +1 -0
  201. package/lib/typescript/src/utils/safeStringify.d.ts +6 -0
  202. package/lib/typescript/src/utils/safeStringify.d.ts.map +1 -0
  203. package/package.json +63 -24
  204. package/src/components/ClipboardTab.tsx +81 -0
  205. package/src/components/ConsoleLogTab.tsx +209 -0
  206. package/src/components/EnvironmentTab.tsx +276 -0
  207. package/src/components/FloatPanelView.tsx +714 -0
  208. package/src/components/NavigationLogTab.tsx +66 -0
  209. package/src/components/NetworkLogTab.tsx +411 -0
  210. package/src/components/ThirdPartyLibsTab.tsx +63 -0
  211. package/src/components/TrackLogTab.tsx +245 -0
  212. package/src/components/ZustandLogTab.tsx +305 -0
  213. package/src/components/shared/CollapsibleSection.tsx +78 -0
  214. package/src/components/shared/CopyButton.tsx +68 -0
  215. package/src/components/shared/JsonView.tsx +125 -0
  216. package/src/core/DebugToolkit.tsx +174 -0
  217. package/src/core/DebugToolkitProvider.tsx +89 -0
  218. package/src/features/ClipboardFeature.ts +11 -0
  219. package/src/features/ConsoleLogFeature.ts +118 -0
  220. package/src/features/EnvironmentFeature.ts +194 -0
  221. package/src/features/NavigationLogFeature.ts +74 -0
  222. package/src/features/NetworkFeature.ts +488 -0
  223. package/src/features/ThirdPartyLibsFeature.ts +42 -0
  224. package/src/features/TrackFeature.ts +69 -0
  225. package/src/features/ZustandLogFeature.ts +127 -0
  226. package/src/hooks/useNavigationLogger.ts +107 -0
  227. package/src/hooks/useSlideDetailAnimation.ts +45 -0
  228. package/src/index.ts +52 -0
  229. package/src/initialize.ts +214 -0
  230. package/src/native/NativeDebugLibs.ts +74 -0
  231. package/src/types/index.ts +138 -0
  232. package/src/utils/constants.ts +91 -0
  233. package/src/utils/copyToComputer.ts +104 -0
  234. package/src/utils/createEventChannel.ts +22 -0
  235. package/src/utils/createObservableStore.ts +42 -0
  236. package/src/utils/safeStringify.ts +25 -0
  237. package/.cursor/rules/react-native.mdc +0 -41
  238. package/README.zh-CN.md +0 -230
  239. package/index.js +0 -41
  240. package/ios/BuildTypeModule.h +0 -9
  241. package/ios/BuildTypeModule.m +0 -42
  242. package/ios/RNDebugLibs.h +0 -10
  243. package/ios/RNDebugLibs.m +0 -79
  244. package/lib/DebugToolKit.js +0 -126
  245. package/lib/EnvironmentManager.ts +0 -80
  246. package/lib/NativeDebugLibs.js +0 -67
  247. package/lib/features/ConsoleLogFeature.js +0 -70
  248. package/lib/features/NavigationLogFeature.js +0 -45
  249. package/lib/features/NetworkFeature.js +0 -389
  250. package/lib/features/PerformanceFeature.js +0 -390
  251. package/lib/features/ThirdPartyLibsFeature.js +0 -63
  252. package/lib/features/TrackFeature.js +0 -94
  253. package/lib/features/ZustandLogFeature.js +0 -44
  254. package/lib/hooks/useNavigationLogger.js +0 -92
  255. package/lib/index.js +0 -114
  256. package/lib/navigation/NavigationLogger.js +0 -1
  257. package/lib/types/TrackTypes.ts +0 -92
  258. package/lib/utils/DebugConst.js +0 -67
  259. package/lib/utils/StorageUtils.js +0 -80
  260. package/lib/views/ConsoleLogDetails.js +0 -314
  261. package/lib/views/FloatPanelView.js +0 -697
  262. package/lib/views/HttpLogDetails.js +0 -648
  263. package/lib/views/NavigationLogDetails.js +0 -302
  264. package/lib/views/RestartModal.js +0 -75
  265. package/lib/views/SubViewConsoleLogs.js +0 -209
  266. package/lib/views/SubViewEnvironment.js +0 -73
  267. package/lib/views/SubViewHTTPLogs.js +0 -235
  268. package/lib/views/SubViewNavigationLogs.js +0 -199
  269. package/lib/views/SubViewPerformance.js +0 -515
  270. package/lib/views/SubViewThirdPartyLibs.js +0 -239
  271. package/lib/views/SubViewTrackLogs.js +0 -318
  272. package/lib/views/SubViewZustandLogs.js +0 -279
  273. package/lib/views/TabView.js +0 -66
  274. package/lib/views/TrackLogDetails.js +0 -481
  275. package/lib/views/ZustandLogDetails.js +0 -355
  276. package/react-native-debug-toolkit.podspec +0 -25
  277. package/react-native.config.js +0 -18
@@ -0,0 +1,127 @@
1
+ import { ZustandLogTab } from '../components/ZustandLogTab';
2
+ import type { DebugFeature, ZustandLogEntry } from '../types';
3
+ import { createEventChannel } from '../utils/createEventChannel';
4
+ import { createObservableStore } from '../utils/createObservableStore';
5
+
6
+ type ZustandLogPayload = Omit<ZustandLogEntry, 'id'>;
7
+
8
+ const DEFAULT_MAX_LOGS = 200;
9
+ const zustandChannel = createEventChannel<ZustandLogPayload>();
10
+
11
+ export const addZustandLog = (
12
+ action: string,
13
+ prevState: unknown,
14
+ nextState: unknown,
15
+ actionCompleteTime?: number,
16
+ storeName?: string,
17
+ ): void => {
18
+ zustandChannel.emit({
19
+ timestamp: Date.now(),
20
+ action,
21
+ prevState,
22
+ nextState,
23
+ actionCompleteTime,
24
+ storeName,
25
+ });
26
+ };
27
+
28
+ type ZustandSetState<T> = (
29
+ partial: T | Partial<T> | ((state: T) => Partial<T> | T),
30
+ replace?: boolean | undefined,
31
+ action?: string | { type: unknown } | undefined,
32
+ ) => void;
33
+
34
+ type ZustandGetState<T> = () => T;
35
+
36
+ interface ZustandStoreApi<T> {
37
+ getState: () => T;
38
+ setState: ZustandSetState<T>;
39
+ subscribe: (listener: (state: T, prevState: T) => void) => () => void;
40
+ name?: string;
41
+ }
42
+
43
+ type ZustandConfig<T> = (
44
+ set: ZustandSetState<T>,
45
+ get: ZustandGetState<T>,
46
+ api: ZustandStoreApi<T>,
47
+ ) => T;
48
+
49
+ /**
50
+ * Zustand middleware that logs all state changes to the debug toolkit.
51
+ *
52
+ * Usage:
53
+ * ```ts
54
+ * const useStore = create(zustandLogMiddleware((set) => ({ ... })))
55
+ * ```
56
+ */
57
+ export const zustandLogMiddleware = <T>(config: ZustandConfig<T>) => (
58
+ set: ZustandSetState<T>,
59
+ get: ZustandGetState<T>,
60
+ api: ZustandStoreApi<T>,
61
+ ) =>
62
+ config(
63
+ (args: Parameters<ZustandSetState<T>>[0], replace?: boolean, actionName?: string | { type: unknown }) => {
64
+ const prevState = get();
65
+ const startTime = Date.now();
66
+ set(args, replace, actionName);
67
+ const duration = Date.now() - startTime;
68
+ const label = typeof actionName === 'string'
69
+ ? actionName
70
+ : typeof args === 'function' ? 'setState' : 'object-set';
71
+ addZustandLog(
72
+ label,
73
+ prevState,
74
+ get(),
75
+ duration,
76
+ api.name,
77
+ );
78
+ },
79
+ get,
80
+ api,
81
+ );
82
+
83
+ export interface ZustandFeatureConfig {
84
+ /** Maximum number of zustand state changes to keep (default: 200) */
85
+ maxLogs?: number;
86
+ }
87
+
88
+ export const createZustandLogFeature = (config?: ZustandFeatureConfig): DebugFeature<ZustandLogEntry> => {
89
+ const maxLogs = config?.maxLogs ?? DEFAULT_MAX_LOGS;
90
+ const logStore = createObservableStore<ZustandLogEntry>();
91
+ let nextId = 0;
92
+ let unsubscribeLogs: (() => void) | null = null;
93
+ let initialized = false;
94
+
95
+ return {
96
+ name: 'zustand',
97
+ label: 'Zustand',
98
+ renderContent: ZustandLogTab,
99
+ setup: () => {
100
+ if (initialized) {
101
+ return;
102
+ }
103
+
104
+ unsubscribeLogs = zustandChannel.subscribe((entry) => {
105
+ logStore.push(
106
+ {
107
+ ...entry,
108
+ id: String(nextId++),
109
+ },
110
+ maxLogs,
111
+ );
112
+ });
113
+ initialized = true;
114
+ },
115
+ getData: () => logStore.getData(),
116
+ clear: () => {
117
+ logStore.clear();
118
+ },
119
+ cleanup: () => {
120
+ unsubscribeLogs?.();
121
+ unsubscribeLogs = null;
122
+ logStore.clear();
123
+ initialized = false;
124
+ },
125
+ subscribe: (listener) => logStore.subscribe(listener),
126
+ };
127
+ };
@@ -0,0 +1,107 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { addNavigationLog } from '../features/NavigationLogFeature';
3
+ import { safeStringify } from '../utils/safeStringify';
4
+
5
+ interface NavigationContainerRef {
6
+ getCurrentRoute?: () => { name?: string } | undefined;
7
+ getRootState?: () => unknown;
8
+ addListener: (event: string, callback: () => void) => () => void;
9
+ }
10
+
11
+ function getActiveRouteName(state: unknown): string {
12
+ let currentState = state as
13
+ | {
14
+ index?: number;
15
+ routes?: Array<{ name?: string; state?: unknown }>;
16
+ }
17
+ | undefined;
18
+
19
+ while (currentState?.routes && typeof currentState.index === 'number') {
20
+ const route = currentState.routes[currentState.index];
21
+ if (!route) {
22
+ return '';
23
+ }
24
+ if (!route.state) {
25
+ return route.name ?? '';
26
+ }
27
+ currentState = route.state as typeof currentState;
28
+ }
29
+
30
+ return '';
31
+ }
32
+
33
+
34
+ /**
35
+ * Hook to automatically log React Navigation events.
36
+ *
37
+ * Usage:
38
+ * ```tsx
39
+ * const navigationRef = useRef<NavigationContainerRef>(null);
40
+ * useNavigationLogger(navigationRef);
41
+ * return <NavigationContainer ref={navigationRef}>...</NavigationContainer>;
42
+ * ```
43
+ */
44
+ export function useNavigationLogger(navigationRef: React.RefObject<NavigationContainerRef | null>) {
45
+ const previousRouteNameRef = useRef('');
46
+
47
+ useEffect(() => {
48
+ let timeoutId: ReturnType<typeof setTimeout> | undefined;
49
+ let unsubscribe: (() => void) | undefined;
50
+ let disposed = false;
51
+
52
+ const attachListener = () => {
53
+ if (disposed) {
54
+ return;
55
+ }
56
+
57
+ const ref = navigationRef.current;
58
+ if (!ref || typeof ref.addListener !== 'function') {
59
+ timeoutId = setTimeout(attachListener, 250);
60
+ return;
61
+ }
62
+
63
+ const currentRouteName =
64
+ ref.getCurrentRoute?.()?.name ||
65
+ getActiveRouteName(ref.getRootState?.());
66
+ if (currentRouteName) {
67
+ previousRouteNameRef.current = currentRouteName;
68
+ }
69
+
70
+ unsubscribe = ref.addListener('state', () => {
71
+ try {
72
+ const navState = ref.getRootState?.();
73
+ const nextRouteName =
74
+ ref.getCurrentRoute?.()?.name ||
75
+ getActiveRouteName(navState);
76
+
77
+ if (!nextRouteName || nextRouteName === previousRouteNameRef.current) {
78
+ return;
79
+ }
80
+
81
+ addNavigationLog(
82
+ 'navigate',
83
+ previousRouteNameRef.current,
84
+ nextRouteName,
85
+ undefined,
86
+ undefined,
87
+ safeStringify(navState),
88
+ );
89
+
90
+ previousRouteNameRef.current = nextRouteName;
91
+ } catch {
92
+ // Navigation state may not be ready
93
+ }
94
+ });
95
+ };
96
+
97
+ attachListener();
98
+
99
+ return () => {
100
+ disposed = true;
101
+ if (timeoutId) {
102
+ clearTimeout(timeoutId);
103
+ }
104
+ unsubscribe?.();
105
+ };
106
+ }, [navigationRef]);
107
+ }
@@ -0,0 +1,45 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { Animated } from 'react-native';
3
+
4
+ /**
5
+ * Shared slide-in/out animation for tab detail views.
6
+ * Returns animated styles for the detail overlay and the list behind it.
7
+ */
8
+ export function useSlideDetailAnimation<T>(
9
+ selected: T | null,
10
+ ): {
11
+ detailTranslateX: Animated.AnimatedInterpolation<number>;
12
+ listTranslateX: Animated.AnimatedInterpolation<number>;
13
+ listOpacity: Animated.AnimatedInterpolation<number>;
14
+ } {
15
+ const slideAnim = useRef(new Animated.Value(0)).current;
16
+ const listSlideAnim = useRef(new Animated.Value(0)).current;
17
+
18
+ useEffect(() => {
19
+ if (selected) {
20
+ listSlideAnim.setValue(0);
21
+ Animated.parallel([
22
+ Animated.spring(slideAnim, { toValue: 1, friction: 9, tension: 60, useNativeDriver: true }),
23
+ Animated.spring(listSlideAnim, { toValue: 1, friction: 9, tension: 60, useNativeDriver: true }),
24
+ ]).start();
25
+ } else {
26
+ slideAnim.setValue(0);
27
+ listSlideAnim.setValue(0);
28
+ }
29
+ }, [selected, slideAnim, listSlideAnim]);
30
+
31
+ const detailTranslateX = slideAnim.interpolate({
32
+ inputRange: [0, 1],
33
+ outputRange: [300, 0],
34
+ });
35
+ const listTranslateX = listSlideAnim.interpolate({
36
+ inputRange: [0, 1],
37
+ outputRange: [0, -60],
38
+ });
39
+ const listOpacity = listSlideAnim.interpolate({
40
+ inputRange: [0, 1],
41
+ outputRange: [1, 0],
42
+ });
43
+
44
+ return { detailTranslateX, listTranslateX, listOpacity };
45
+ }
package/src/index.ts ADDED
@@ -0,0 +1,52 @@
1
+ // Core
2
+ export { DebugToolkit } from './core/DebugToolkit';
3
+ export { DebugToolkitProvider, useDebugToolkit } from './core/DebugToolkitProvider';
4
+ export { initializeDebugToolkit, isDebugMode } from './initialize';
5
+ export type { InitializeOptions, FeatureConfigs } from './initialize';
6
+
7
+ // Feature factories
8
+ export { createNetworkFeature } from './features/NetworkFeature';
9
+ export type { NetworkFeatureAPI, NetworkFeatureConfig } from './features/NetworkFeature';
10
+ export { createConsoleLogFeature } from './features/ConsoleLogFeature';
11
+ export type { ConsoleFeatureConfig } from './features/ConsoleLogFeature';
12
+ export { createZustandLogFeature, zustandLogMiddleware, addZustandLog } from './features/ZustandLogFeature';
13
+ export type { ZustandFeatureConfig } from './features/ZustandLogFeature';
14
+ export { createNavigationLogFeature, addNavigationLog } from './features/NavigationLogFeature';
15
+ export type { NavigationFeatureConfig } from './features/NavigationLogFeature';
16
+ export { createTrackFeature, addTrackLog } from './features/TrackFeature';
17
+ export type { TrackFeatureConfig, TrackEventData } from './features/TrackFeature';
18
+ export { createThirdPartyLibsFeature } from './features/ThirdPartyLibsFeature';
19
+ export { createEnvironmentFeature } from './features/EnvironmentFeature';
20
+ export type { EnvironmentFeatureAPI } from './features/EnvironmentFeature';
21
+ export { createClipboardFeature } from './features/ClipboardFeature';
22
+
23
+ // Hooks
24
+ export { useNavigationLogger } from './hooks/useNavigationLogger';
25
+ export { useSlideDetailAnimation } from './hooks/useSlideDetailAnimation';
26
+
27
+ // Utilities
28
+ export { safeStringify } from './utils/safeStringify';
29
+ export { copyToComputer, logToComputer, fmt } from './utils/copyToComputer';
30
+ export type { CopyResult, CopyOptions, CopyMethod } from './utils/copyToComputer';
31
+
32
+ // Types
33
+ export type {
34
+ BuiltInFeatureName,
35
+ DebugFeature,
36
+ DebugFeatureFactory,
37
+ DebugFeatureInput,
38
+ DebugFeatureRenderProps,
39
+ DebugToolkitConfig,
40
+ DebugToolkitAPI,
41
+ NetworkLogEntry,
42
+ ConsoleLogEntry,
43
+ ZustandLogEntry,
44
+ NavigationLogEntry,
45
+ TrackLogEntry,
46
+ ThirdPartyLib,
47
+ EnvironmentConfig,
48
+ EnvironmentState,
49
+ } from './types';
50
+
51
+ // Default export for convenience
52
+ export { initializeDebugToolkit as default } from './initialize';
@@ -0,0 +1,214 @@
1
+ import { DebugToolkit } from './core/DebugToolkit';
2
+ import { createNetworkFeature } from './features/NetworkFeature';
3
+ import type { NetworkFeatureConfig } from './features/NetworkFeature';
4
+ import { createConsoleLogFeature } from './features/ConsoleLogFeature';
5
+ import type { ConsoleFeatureConfig } from './features/ConsoleLogFeature';
6
+ import { createZustandLogFeature } from './features/ZustandLogFeature';
7
+ import type { ZustandFeatureConfig } from './features/ZustandLogFeature';
8
+ import { createNavigationLogFeature } from './features/NavigationLogFeature';
9
+ import type { NavigationFeatureConfig } from './features/NavigationLogFeature';
10
+ import { createTrackFeature } from './features/TrackFeature';
11
+ import type { TrackFeatureConfig } from './features/TrackFeature';
12
+ import { createThirdPartyLibsFeature } from './features/ThirdPartyLibsFeature';
13
+ import { createEnvironmentFeature } from './features/EnvironmentFeature';
14
+ import { createClipboardFeature } from './features/ClipboardFeature';
15
+ import { NativeDebugLibs } from './native/NativeDebugLibs';
16
+ import type {
17
+ BuiltInFeatureName,
18
+ DebugFeature,
19
+ DebugFeatureInput,
20
+ } from './types';
21
+
22
+ export const isDebugMode = __DEV__;
23
+
24
+ /** Feature-specific configuration map */
25
+ export interface FeatureConfigs {
26
+ network?: boolean | NetworkFeatureConfig;
27
+ console?: boolean | ConsoleFeatureConfig;
28
+ zustand?: boolean | ZustandFeatureConfig;
29
+ navigation?: boolean | NavigationFeatureConfig;
30
+ track?: boolean | TrackFeatureConfig;
31
+ thirdPartyLibs?: boolean;
32
+ environment?: Parameters<typeof createEnvironmentFeature>[0];
33
+ clipboard?: boolean;
34
+ }
35
+
36
+ export interface InitializeOptions {
37
+ doraemonProductId?: string;
38
+ enabled?: boolean;
39
+ }
40
+
41
+ /** Registry mapping feature names to creator functions */
42
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
+ const featureRegistry: Record<BuiltInFeatureName, (config?: any) => DebugFeature<any>> = {
44
+ network: createNetworkFeature,
45
+ console: createConsoleLogFeature,
46
+ zustand: createZustandLogFeature,
47
+ navigation: createNavigationLogFeature,
48
+ track: createTrackFeature,
49
+ thirdPartyLibs: createThirdPartyLibsFeature,
50
+ environment: createEnvironmentFeature,
51
+ clipboard: createClipboardFeature,
52
+ };
53
+
54
+ const DEFAULT_FEATURES: BuiltInFeatureName[] = [
55
+ 'network',
56
+ 'console',
57
+ 'navigation',
58
+ 'zustand',
59
+ 'track',
60
+ 'thirdPartyLibs',
61
+ 'clipboard',
62
+ ];
63
+
64
+ function resolveFeatures(
65
+ features: DebugFeatureInput[],
66
+ ): DebugFeature<any>[] {
67
+ return features.reduce<DebugFeature<any>[]>((resolvedFeatures, identifier) => {
68
+ let feature: DebugFeature<any> | null = null;
69
+
70
+ if (typeof identifier === 'string') {
71
+ const creator = featureRegistry[identifier as BuiltInFeatureName];
72
+ if (!creator) {
73
+ console.warn(`[DebugToolkit] Unknown feature: "${identifier}"`);
74
+ return resolvedFeatures;
75
+ }
76
+ feature = creator();
77
+ } else if (typeof identifier === 'function') {
78
+ try {
79
+ feature = identifier();
80
+ } catch (error) {
81
+ console.error('[DebugToolkit] Feature creator failed:', error);
82
+ return resolvedFeatures;
83
+ }
84
+ } else if (identifier && typeof identifier === 'object' && identifier.name) {
85
+ feature = identifier;
86
+ } else {
87
+ console.warn('[DebugToolkit] Invalid feature identifier:', identifier);
88
+ return resolvedFeatures;
89
+ }
90
+
91
+ if (feature) {
92
+ resolvedFeatures.push(feature);
93
+ }
94
+
95
+ return resolvedFeatures;
96
+ }, []);
97
+ }
98
+
99
+ /**
100
+ * Resolve feature configs to DebugFeature instances.
101
+ */
102
+ function resolveFeatureConfigs(configs: FeatureConfigs): DebugFeature<any>[] {
103
+ const features: DebugFeature<any>[] = [];
104
+
105
+ const entries = Object.entries(configs) as [BuiltInFeatureName, unknown][];
106
+
107
+ for (const [name, config] of entries) {
108
+ // Skip false/explicitly disabled
109
+ if (config === false) continue;
110
+
111
+ const creator = featureRegistry[name];
112
+ if (!creator) {
113
+ console.warn(`[DebugToolkit] Unknown feature: "${name}"`);
114
+ continue;
115
+ }
116
+
117
+ // config === true or undefined → use defaults
118
+ if (config === true || config === undefined) {
119
+ features.push(creator());
120
+ } else if (typeof config === 'object') {
121
+ features.push(creator(config as Record<string, unknown>));
122
+ }
123
+ }
124
+
125
+ return features;
126
+ }
127
+
128
+ /**
129
+ * Initialize the debug toolkit.
130
+ *
131
+ * @param featuresOrOptions - Either an array of feature inputs (legacy), or a full config object.
132
+ * @param options - Options when using legacy array mode.
133
+ *
134
+ * @example
135
+ * // Legacy mode (still supported)
136
+ * initializeDebugToolkit(['network', 'console'], { enabled: true });
137
+ *
138
+ * // Config object mode (recommended)
139
+ * initializeDebugToolkit({
140
+ * features: {
141
+ * network: { maxLogs: 100 },
142
+ * console: true,
143
+ * track: true,
144
+ * environment: { environments: [...] },
145
+ * },
146
+ * enabled: true,
147
+ * });
148
+ */
149
+ export function initializeDebugToolkit(
150
+ featuresOrOptions?: DebugFeatureInput[] | {
151
+ features?: FeatureConfigs;
152
+ enabled?: boolean;
153
+ doraemonProductId?: string;
154
+ },
155
+ options: InitializeOptions = {},
156
+ ): DebugToolkit | null {
157
+ // Determine which mode we're in
158
+ let resolvedFeatures: DebugFeature<any>[];
159
+ let enabled: boolean;
160
+ let doraemonProductId: string | undefined;
161
+
162
+ if (Array.isArray(featuresOrOptions)) {
163
+ // Legacy mode
164
+ resolvedFeatures = resolveFeatures(featuresOrOptions);
165
+ enabled = options.enabled ?? isDebugMode;
166
+ doraemonProductId = options.doraemonProductId;
167
+ } else if (featuresOrOptions && typeof featuresOrOptions === 'object' && !('name' in featuresOrOptions)) {
168
+ // Config object mode
169
+ const config = featuresOrOptions;
170
+ enabled = config.enabled ?? isDebugMode;
171
+ doraemonProductId = config.doraemonProductId;
172
+
173
+ if (config.features) {
174
+ resolvedFeatures = resolveFeatureConfigs(config.features);
175
+ } else {
176
+ resolvedFeatures = resolveFeatures(DEFAULT_FEATURES);
177
+ }
178
+ } else {
179
+ // Default - no args or single feature
180
+ resolvedFeatures = resolveFeatures(
181
+ featuresOrOptions ? [featuresOrOptions as DebugFeatureInput] : DEFAULT_FEATURES,
182
+ );
183
+ enabled = options.enabled ?? isDebugMode;
184
+ doraemonProductId = options.doraemonProductId;
185
+ }
186
+
187
+ try {
188
+ const toolkit = DebugToolkit.getInstance(enabled);
189
+ toolkit.setEnabled(enabled);
190
+
191
+ if (!enabled) {
192
+ toolkit.reset();
193
+ return toolkit;
194
+ }
195
+
196
+ // Initialize native debug libs if configured
197
+ if (doraemonProductId) {
198
+ NativeDebugLibs.installDoraemonKit(doraemonProductId);
199
+ }
200
+
201
+ toolkit.replaceFeatures(resolvedFeatures);
202
+
203
+ if (toolkit.hasFeatures()) {
204
+ toolkit.showPanel();
205
+ } else {
206
+ toolkit.hidePanel();
207
+ }
208
+
209
+ return toolkit;
210
+ } catch (error) {
211
+ console.error('[DebugToolkit] Initialization failed:', error);
212
+ return null;
213
+ }
214
+ }
@@ -0,0 +1,74 @@
1
+ import { NativeModules, Platform } from 'react-native';
2
+
3
+ interface RNDebugLibsType {
4
+ showExplorer?(): void;
5
+ hideExplorer?(): void;
6
+ toggleExplorer?(): void;
7
+ installDoraemonKit?(productId: string): void;
8
+ showDoraemonKit?(): void;
9
+ hideDoraemonKit?(): void;
10
+ }
11
+
12
+ interface BuildTypeModuleType {
13
+ getBuildType(): Promise<string | null>;
14
+ getBuildTypeSync(): string | null;
15
+ }
16
+
17
+ const RNDebugLibs: RNDebugLibsType = NativeModules.RNDebugLibs ?? {};
18
+ const BuildTypeModule: BuildTypeModuleType | null = NativeModules.BuildTypeModule ?? null;
19
+
20
+ export const NativeDebugLibs = {
21
+ getBuildType(): Promise<string | null> {
22
+ if (BuildTypeModule) {
23
+ return BuildTypeModule.getBuildType();
24
+ }
25
+ return Promise.resolve(null);
26
+ },
27
+
28
+ getBuildTypeSync(): string | null {
29
+ if (BuildTypeModule) {
30
+ return BuildTypeModule.getBuildTypeSync();
31
+ }
32
+ return null;
33
+ },
34
+
35
+ isDebugBuild(): boolean {
36
+ if (BuildTypeModule) {
37
+ return BuildTypeModule.getBuildTypeSync() === 'debug';
38
+ }
39
+ // Fallback: assume __DEV__ is the source of truth
40
+ return __DEV__;
41
+ },
42
+
43
+ // FLEX (iOS only)
44
+ showExplorer(): void {
45
+ if (Platform.OS === 'ios' && RNDebugLibs.showExplorer) {
46
+ RNDebugLibs.showExplorer();
47
+ }
48
+ },
49
+
50
+ hideExplorer(): void {
51
+ if (Platform.OS === 'ios' && RNDebugLibs.hideExplorer) {
52
+ RNDebugLibs.hideExplorer();
53
+ }
54
+ },
55
+
56
+ // DoraemonKit
57
+ installDoraemonKit(productId: string): void {
58
+ if (RNDebugLibs.installDoraemonKit) {
59
+ RNDebugLibs.installDoraemonKit(productId);
60
+ }
61
+ },
62
+
63
+ showDoraemonKit(): void {
64
+ if (RNDebugLibs.showDoraemonKit) {
65
+ RNDebugLibs.showDoraemonKit();
66
+ }
67
+ },
68
+
69
+ hideDoraemonKit(): void {
70
+ if (RNDebugLibs.hideDoraemonKit) {
71
+ RNDebugLibs.hideDoraemonKit();
72
+ }
73
+ },
74
+ };