@mobileai/react-native 0.9.17 → 0.9.19

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 (292) hide show
  1. package/LICENSE +28 -20
  2. package/MobileAIFloatingOverlay.podspec +25 -0
  3. package/android/build.gradle +61 -0
  4. package/android/src/main/AndroidManifest.xml +3 -0
  5. package/android/src/main/java/com/mobileai/overlay/FloatingOverlayView.kt +151 -0
  6. package/android/src/main/java/com/mobileai/overlay/MobileAIOverlayPackage.kt +23 -0
  7. package/android/src/newarch/com/mobileai/overlay/FloatingOverlayViewManager.kt +45 -0
  8. package/android/src/oldarch/com/mobileai/overlay/FloatingOverlayViewManager.kt +29 -0
  9. package/ios/MobileAIFloatingOverlayComponentView.mm +73 -0
  10. package/lib/module/components/AIAgent.js +902 -136
  11. package/lib/module/components/AIConsentDialog.js +439 -0
  12. package/lib/module/components/AgentChatBar.js +828 -134
  13. package/lib/module/components/AgentOverlay.js +2 -1
  14. package/lib/module/components/DiscoveryTooltip.js +21 -9
  15. package/lib/module/components/FloatingOverlayWrapper.js +108 -0
  16. package/lib/module/components/Icons.js +123 -0
  17. package/lib/module/config/endpoints.js +12 -2
  18. package/lib/module/core/AgentRuntime.js +373 -27
  19. package/lib/module/core/FiberAdapter.js +56 -0
  20. package/lib/module/core/FiberTreeWalker.js +186 -80
  21. package/lib/module/core/IdleDetector.js +19 -0
  22. package/lib/module/core/NativeAlertInterceptor.js +191 -0
  23. package/lib/module/core/systemPrompt.js +203 -45
  24. package/lib/module/index.js +3 -0
  25. package/lib/module/providers/GeminiProvider.js +72 -56
  26. package/lib/module/providers/ProviderFactory.js +6 -2
  27. package/lib/module/services/AudioInputService.js +3 -12
  28. package/lib/module/services/AudioOutputService.js +1 -13
  29. package/lib/module/services/ConversationService.js +166 -0
  30. package/lib/module/services/MobileAIKnowledgeRetriever.js +41 -0
  31. package/lib/module/services/VoiceService.js +29 -8
  32. package/lib/module/services/telemetry/MobileAI.js +44 -0
  33. package/lib/module/services/telemetry/TelemetryService.js +13 -1
  34. package/lib/module/services/telemetry/TouchAutoCapture.js +44 -18
  35. package/lib/module/specs/FloatingOverlayNativeComponent.ts +19 -0
  36. package/lib/module/support/CSATSurvey.js +95 -12
  37. package/lib/module/support/EscalationSocket.js +70 -1
  38. package/lib/module/support/ReportedIssueEventSource.js +148 -0
  39. package/lib/module/support/escalateTool.js +4 -2
  40. package/lib/module/support/index.js +1 -0
  41. package/lib/module/support/reportIssueTool.js +127 -0
  42. package/lib/module/support/supportPrompt.js +77 -9
  43. package/lib/module/tools/guideTool.js +2 -1
  44. package/lib/module/tools/longPressTool.js +4 -3
  45. package/lib/module/tools/pickerTool.js +6 -4
  46. package/lib/module/tools/tapTool.js +12 -3
  47. package/lib/module/tools/typeTool.js +19 -10
  48. package/lib/module/utils/logger.js +175 -6
  49. package/lib/typescript/react-native.config.d.ts +11 -0
  50. package/lib/typescript/src/components/AIAgent.d.ts +28 -2
  51. package/lib/typescript/src/components/AIConsentDialog.d.ts +153 -0
  52. package/lib/typescript/src/components/AgentChatBar.d.ts +15 -2
  53. package/lib/typescript/src/components/DiscoveryTooltip.d.ts +3 -1
  54. package/lib/typescript/src/components/FloatingOverlayWrapper.d.ts +51 -0
  55. package/lib/typescript/src/components/Icons.d.ts +8 -0
  56. package/lib/typescript/src/config/endpoints.d.ts +5 -3
  57. package/lib/typescript/src/core/AgentRuntime.d.ts +4 -0
  58. package/lib/typescript/src/core/FiberAdapter.d.ts +25 -0
  59. package/lib/typescript/src/core/FiberTreeWalker.d.ts +2 -0
  60. package/lib/typescript/src/core/IdleDetector.d.ts +11 -0
  61. package/lib/typescript/src/core/NativeAlertInterceptor.d.ts +55 -0
  62. package/lib/typescript/src/core/types.d.ts +106 -1
  63. package/lib/typescript/src/index.d.ts +9 -4
  64. package/lib/typescript/src/providers/GeminiProvider.d.ts +6 -5
  65. package/lib/typescript/src/services/ConversationService.d.ts +55 -0
  66. package/lib/typescript/src/services/MobileAIKnowledgeRetriever.d.ts +9 -0
  67. package/lib/typescript/src/services/telemetry/MobileAI.d.ts +7 -0
  68. package/lib/typescript/src/services/telemetry/TelemetryService.d.ts +1 -1
  69. package/lib/typescript/src/services/telemetry/TouchAutoCapture.d.ts +9 -6
  70. package/lib/typescript/src/services/telemetry/types.d.ts +3 -1
  71. package/lib/typescript/src/specs/FloatingOverlayNativeComponent.d.ts +17 -0
  72. package/lib/typescript/src/support/EscalationSocket.d.ts +17 -0
  73. package/lib/typescript/src/support/ReportedIssueEventSource.d.ts +24 -0
  74. package/lib/typescript/src/support/escalateTool.d.ts +5 -0
  75. package/lib/typescript/src/support/index.d.ts +2 -1
  76. package/lib/typescript/src/support/reportIssueTool.d.ts +20 -0
  77. package/lib/typescript/src/support/types.d.ts +56 -1
  78. package/lib/typescript/src/utils/logger.d.ts +15 -0
  79. package/package.json +20 -9
  80. package/react-native.config.js +12 -0
  81. package/lib/module/__cli_tmp__.js.map +0 -1
  82. package/lib/module/components/AIAgent.js.map +0 -1
  83. package/lib/module/components/AIZone.js.map +0 -1
  84. package/lib/module/components/AgentChatBar.js.map +0 -1
  85. package/lib/module/components/AgentErrorBoundary.js.map +0 -1
  86. package/lib/module/components/AgentOverlay.js.map +0 -1
  87. package/lib/module/components/DiscoveryTooltip.js.map +0 -1
  88. package/lib/module/components/HighlightOverlay.js.map +0 -1
  89. package/lib/module/components/Icons.js.map +0 -1
  90. package/lib/module/components/ProactiveHint.js.map +0 -1
  91. package/lib/module/components/cards/InfoCard.js.map +0 -1
  92. package/lib/module/components/cards/ReviewSummary.js.map +0 -1
  93. package/lib/module/config/endpoints.js.map +0 -1
  94. package/lib/module/core/ActionRegistry.js.map +0 -1
  95. package/lib/module/core/AgentRuntime.js.map +0 -1
  96. package/lib/module/core/FiberTreeWalker.js.map +0 -1
  97. package/lib/module/core/IdleDetector.js.map +0 -1
  98. package/lib/module/core/MCPBridge.js.map +0 -1
  99. package/lib/module/core/ScreenDehydrator.js.map +0 -1
  100. package/lib/module/core/ZoneRegistry.js.map +0 -1
  101. package/lib/module/core/systemPrompt.js.map +0 -1
  102. package/lib/module/core/types.js.map +0 -1
  103. package/lib/module/hooks/useAction.js.map +0 -1
  104. package/lib/module/index.js.map +0 -1
  105. package/lib/module/plugin/withAppIntents.js.map +0 -1
  106. package/lib/module/providers/GeminiProvider.js.map +0 -1
  107. package/lib/module/providers/OpenAIProvider.js.map +0 -1
  108. package/lib/module/providers/ProviderFactory.js.map +0 -1
  109. package/lib/module/services/AudioInputService.js.map +0 -1
  110. package/lib/module/services/AudioOutputService.js.map +0 -1
  111. package/lib/module/services/KnowledgeBaseService.js.map +0 -1
  112. package/lib/module/services/VoiceService.js.map +0 -1
  113. package/lib/module/services/flags/FlagService.js.map +0 -1
  114. package/lib/module/services/telemetry/MobileAI.js.map +0 -1
  115. package/lib/module/services/telemetry/PiiScrubber.js.map +0 -1
  116. package/lib/module/services/telemetry/TelemetryService.js.map +0 -1
  117. package/lib/module/services/telemetry/TouchAutoCapture.js.map +0 -1
  118. package/lib/module/services/telemetry/device.js.map +0 -1
  119. package/lib/module/services/telemetry/deviceMetadata.js.map +0 -1
  120. package/lib/module/services/telemetry/index.js.map +0 -1
  121. package/lib/module/services/telemetry/types.js.map +0 -1
  122. package/lib/module/support/CSATSurvey.js.map +0 -1
  123. package/lib/module/support/EscalationEventSource.js.map +0 -1
  124. package/lib/module/support/EscalationSocket.js.map +0 -1
  125. package/lib/module/support/SupportChatModal.js.map +0 -1
  126. package/lib/module/support/SupportGreeting.js.map +0 -1
  127. package/lib/module/support/TicketStore.js.map +0 -1
  128. package/lib/module/support/escalateTool.js.map +0 -1
  129. package/lib/module/support/index.js.map +0 -1
  130. package/lib/module/support/supportPrompt.js.map +0 -1
  131. package/lib/module/support/types.js.map +0 -1
  132. package/lib/module/tools/datePickerTool.js.map +0 -1
  133. package/lib/module/tools/guideTool.js.map +0 -1
  134. package/lib/module/tools/index.js.map +0 -1
  135. package/lib/module/tools/keyboardTool.js.map +0 -1
  136. package/lib/module/tools/longPressTool.js.map +0 -1
  137. package/lib/module/tools/pickerTool.js.map +0 -1
  138. package/lib/module/tools/restoreTool.js.map +0 -1
  139. package/lib/module/tools/scrollTool.js.map +0 -1
  140. package/lib/module/tools/simplifyTool.js.map +0 -1
  141. package/lib/module/tools/sliderTool.js.map +0 -1
  142. package/lib/module/tools/tapTool.js.map +0 -1
  143. package/lib/module/tools/typeTool.js.map +0 -1
  144. package/lib/module/tools/types.js.map +0 -1
  145. package/lib/module/types/jsx.d.js.map +0 -1
  146. package/lib/module/utils/audioUtils.js.map +0 -1
  147. package/lib/module/utils/logger.js.map +0 -1
  148. package/lib/typescript/babel.config.d.ts.map +0 -1
  149. package/lib/typescript/bin/generate-map.d.cts.map +0 -1
  150. package/lib/typescript/eslint.config.d.mts.map +0 -1
  151. package/lib/typescript/generate-map.d.ts.map +0 -1
  152. package/lib/typescript/src/__cli_tmp__.d.ts.map +0 -1
  153. package/lib/typescript/src/components/AIAgent.d.ts.map +0 -1
  154. package/lib/typescript/src/components/AIZone.d.ts.map +0 -1
  155. package/lib/typescript/src/components/AgentChatBar.d.ts.map +0 -1
  156. package/lib/typescript/src/components/AgentErrorBoundary.d.ts.map +0 -1
  157. package/lib/typescript/src/components/AgentOverlay.d.ts.map +0 -1
  158. package/lib/typescript/src/components/DiscoveryTooltip.d.ts.map +0 -1
  159. package/lib/typescript/src/components/HighlightOverlay.d.ts.map +0 -1
  160. package/lib/typescript/src/components/Icons.d.ts.map +0 -1
  161. package/lib/typescript/src/components/ProactiveHint.d.ts.map +0 -1
  162. package/lib/typescript/src/components/cards/InfoCard.d.ts.map +0 -1
  163. package/lib/typescript/src/components/cards/ReviewSummary.d.ts.map +0 -1
  164. package/lib/typescript/src/config/endpoints.d.ts.map +0 -1
  165. package/lib/typescript/src/core/ActionRegistry.d.ts.map +0 -1
  166. package/lib/typescript/src/core/AgentRuntime.d.ts.map +0 -1
  167. package/lib/typescript/src/core/FiberTreeWalker.d.ts.map +0 -1
  168. package/lib/typescript/src/core/IdleDetector.d.ts.map +0 -1
  169. package/lib/typescript/src/core/MCPBridge.d.ts.map +0 -1
  170. package/lib/typescript/src/core/ScreenDehydrator.d.ts.map +0 -1
  171. package/lib/typescript/src/core/ZoneRegistry.d.ts.map +0 -1
  172. package/lib/typescript/src/core/systemPrompt.d.ts.map +0 -1
  173. package/lib/typescript/src/core/types.d.ts.map +0 -1
  174. package/lib/typescript/src/hooks/useAction.d.ts.map +0 -1
  175. package/lib/typescript/src/index.d.ts.map +0 -1
  176. package/lib/typescript/src/plugin/withAppIntents.d.ts.map +0 -1
  177. package/lib/typescript/src/providers/GeminiProvider.d.ts.map +0 -1
  178. package/lib/typescript/src/providers/OpenAIProvider.d.ts.map +0 -1
  179. package/lib/typescript/src/providers/ProviderFactory.d.ts.map +0 -1
  180. package/lib/typescript/src/services/AudioInputService.d.ts.map +0 -1
  181. package/lib/typescript/src/services/AudioOutputService.d.ts.map +0 -1
  182. package/lib/typescript/src/services/KnowledgeBaseService.d.ts.map +0 -1
  183. package/lib/typescript/src/services/VoiceService.d.ts.map +0 -1
  184. package/lib/typescript/src/services/flags/FlagService.d.ts.map +0 -1
  185. package/lib/typescript/src/services/telemetry/MobileAI.d.ts.map +0 -1
  186. package/lib/typescript/src/services/telemetry/PiiScrubber.d.ts.map +0 -1
  187. package/lib/typescript/src/services/telemetry/TelemetryService.d.ts.map +0 -1
  188. package/lib/typescript/src/services/telemetry/TouchAutoCapture.d.ts.map +0 -1
  189. package/lib/typescript/src/services/telemetry/device.d.ts.map +0 -1
  190. package/lib/typescript/src/services/telemetry/deviceMetadata.d.ts.map +0 -1
  191. package/lib/typescript/src/services/telemetry/index.d.ts.map +0 -1
  192. package/lib/typescript/src/services/telemetry/types.d.ts.map +0 -1
  193. package/lib/typescript/src/support/CSATSurvey.d.ts.map +0 -1
  194. package/lib/typescript/src/support/EscalationEventSource.d.ts.map +0 -1
  195. package/lib/typescript/src/support/EscalationSocket.d.ts.map +0 -1
  196. package/lib/typescript/src/support/SupportChatModal.d.ts.map +0 -1
  197. package/lib/typescript/src/support/SupportGreeting.d.ts.map +0 -1
  198. package/lib/typescript/src/support/TicketStore.d.ts.map +0 -1
  199. package/lib/typescript/src/support/escalateTool.d.ts.map +0 -1
  200. package/lib/typescript/src/support/index.d.ts.map +0 -1
  201. package/lib/typescript/src/support/supportPrompt.d.ts.map +0 -1
  202. package/lib/typescript/src/support/types.d.ts.map +0 -1
  203. package/lib/typescript/src/tools/datePickerTool.d.ts.map +0 -1
  204. package/lib/typescript/src/tools/guideTool.d.ts.map +0 -1
  205. package/lib/typescript/src/tools/index.d.ts.map +0 -1
  206. package/lib/typescript/src/tools/keyboardTool.d.ts.map +0 -1
  207. package/lib/typescript/src/tools/longPressTool.d.ts.map +0 -1
  208. package/lib/typescript/src/tools/pickerTool.d.ts.map +0 -1
  209. package/lib/typescript/src/tools/restoreTool.d.ts.map +0 -1
  210. package/lib/typescript/src/tools/scrollTool.d.ts.map +0 -1
  211. package/lib/typescript/src/tools/simplifyTool.d.ts.map +0 -1
  212. package/lib/typescript/src/tools/sliderTool.d.ts.map +0 -1
  213. package/lib/typescript/src/tools/tapTool.d.ts.map +0 -1
  214. package/lib/typescript/src/tools/typeTool.d.ts.map +0 -1
  215. package/lib/typescript/src/tools/types.d.ts.map +0 -1
  216. package/lib/typescript/src/utils/audioUtils.d.ts.map +0 -1
  217. package/lib/typescript/src/utils/logger.d.ts.map +0 -1
  218. package/src/__cli_tmp__.tsx +0 -9
  219. package/src/cli/analyzers/chain-analyzer.ts +0 -183
  220. package/src/cli/extractors/ai-extractor.ts +0 -6
  221. package/src/cli/extractors/ast-extractor.ts +0 -551
  222. package/src/cli/generate-intents.ts +0 -140
  223. package/src/cli/generate-map.ts +0 -121
  224. package/src/cli/generate-swift.ts +0 -116
  225. package/src/cli/scanners/expo-scanner.ts +0 -203
  226. package/src/cli/scanners/rn-scanner.ts +0 -445
  227. package/src/components/AIAgent.tsx +0 -1716
  228. package/src/components/AIZone.tsx +0 -147
  229. package/src/components/AgentChatBar.tsx +0 -1143
  230. package/src/components/AgentErrorBoundary.tsx +0 -78
  231. package/src/components/AgentOverlay.tsx +0 -73
  232. package/src/components/DiscoveryTooltip.tsx +0 -148
  233. package/src/components/HighlightOverlay.tsx +0 -136
  234. package/src/components/Icons.tsx +0 -253
  235. package/src/components/ProactiveHint.tsx +0 -145
  236. package/src/components/cards/InfoCard.tsx +0 -58
  237. package/src/components/cards/ReviewSummary.tsx +0 -76
  238. package/src/config/endpoints.ts +0 -22
  239. package/src/core/ActionRegistry.ts +0 -105
  240. package/src/core/AgentRuntime.ts +0 -1471
  241. package/src/core/FiberTreeWalker.ts +0 -930
  242. package/src/core/IdleDetector.ts +0 -72
  243. package/src/core/MCPBridge.ts +0 -163
  244. package/src/core/ScreenDehydrator.ts +0 -53
  245. package/src/core/ZoneRegistry.ts +0 -44
  246. package/src/core/systemPrompt.ts +0 -431
  247. package/src/core/types.ts +0 -521
  248. package/src/hooks/useAction.ts +0 -182
  249. package/src/index.ts +0 -83
  250. package/src/plugin/withAppIntents.ts +0 -98
  251. package/src/providers/GeminiProvider.ts +0 -357
  252. package/src/providers/OpenAIProvider.ts +0 -379
  253. package/src/providers/ProviderFactory.ts +0 -36
  254. package/src/services/AudioInputService.ts +0 -226
  255. package/src/services/AudioOutputService.ts +0 -236
  256. package/src/services/KnowledgeBaseService.ts +0 -156
  257. package/src/services/VoiceService.ts +0 -451
  258. package/src/services/flags/FlagService.ts +0 -137
  259. package/src/services/telemetry/MobileAI.ts +0 -66
  260. package/src/services/telemetry/PiiScrubber.ts +0 -17
  261. package/src/services/telemetry/TelemetryService.ts +0 -323
  262. package/src/services/telemetry/TouchAutoCapture.ts +0 -165
  263. package/src/services/telemetry/device.ts +0 -93
  264. package/src/services/telemetry/deviceMetadata.ts +0 -13
  265. package/src/services/telemetry/index.ts +0 -13
  266. package/src/services/telemetry/types.ts +0 -75
  267. package/src/support/CSATSurvey.tsx +0 -304
  268. package/src/support/EscalationEventSource.ts +0 -190
  269. package/src/support/EscalationSocket.ts +0 -152
  270. package/src/support/SupportChatModal.tsx +0 -563
  271. package/src/support/SupportGreeting.tsx +0 -161
  272. package/src/support/TicketStore.ts +0 -100
  273. package/src/support/escalateTool.ts +0 -174
  274. package/src/support/index.ts +0 -29
  275. package/src/support/supportPrompt.ts +0 -55
  276. package/src/support/types.ts +0 -155
  277. package/src/tools/datePickerTool.ts +0 -60
  278. package/src/tools/guideTool.ts +0 -76
  279. package/src/tools/index.ts +0 -20
  280. package/src/tools/keyboardTool.ts +0 -30
  281. package/src/tools/longPressTool.ts +0 -61
  282. package/src/tools/pickerTool.ts +0 -115
  283. package/src/tools/restoreTool.ts +0 -33
  284. package/src/tools/scrollTool.ts +0 -156
  285. package/src/tools/simplifyTool.ts +0 -33
  286. package/src/tools/sliderTool.ts +0 -65
  287. package/src/tools/tapTool.ts +0 -93
  288. package/src/tools/typeTool.ts +0 -113
  289. package/src/tools/types.ts +0 -58
  290. package/src/types/jsx.d.ts +0 -20
  291. package/src/utils/audioUtils.ts +0 -54
  292. package/src/utils/logger.ts +0 -38
@@ -1,445 +0,0 @@
1
- /**
2
- * React Navigation scanner.
3
- * Discovers screens by parsing navigation config files.
4
- * Supports v5/v6 (dynamic JSX) and v7 (static object) patterns.
5
- */
6
-
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
- import { parse } from '@babel/parser';
10
- import * as _traverse from '@babel/traverse';
11
- import * as t from '@babel/types';
12
-
13
- const traverse = (_traverse as any).default || _traverse;
14
- import { extractContentFromAST, buildDescription } from '../extractors/ast-extractor';
15
-
16
- export interface ScannedScreen {
17
- routeName: string;
18
- filePath: string;
19
- title?: string;
20
- description: string;
21
- navigationLinks: string[];
22
- }
23
-
24
- const NAVIGATOR_FUNCTIONS = [
25
- 'createStackNavigator',
26
- 'createNativeStackNavigator',
27
- 'createBottomTabNavigator',
28
- 'createDrawerNavigator',
29
- 'createMaterialBottomTabNavigator',
30
- 'createMaterialTopTabNavigator',
31
- ];
32
-
33
- /**
34
- * Scan a React Navigation project and return all screens.
35
- */
36
- export function scanReactNavigationApp(projectRoot: string): ScannedScreen[] {
37
- console.log(`[generate-map] Scanning React Navigation project: ${projectRoot}`);
38
-
39
- // Find all JS/TS files that contain navigator creation
40
- const navigatorFiles = findNavigatorFiles(projectRoot);
41
-
42
- if (navigatorFiles.length === 0) {
43
- throw new Error(
44
- 'Could not find any React Navigation navigator definitions. ' +
45
- 'Searched for createStackNavigator, createNativeStackNavigator, etc.'
46
- );
47
- }
48
-
49
- console.log(`[generate-map] Found ${navigatorFiles.length} navigator file(s)`);
50
-
51
- const screens: ScannedScreen[] = [];
52
- const processedRoutes = new Set<string>();
53
- const fileAstCache = new Map<string, any>();
54
-
55
- for (const navFile of navigatorFiles) {
56
- const sourceCode = fs.readFileSync(navFile, 'utf-8');
57
- const screenDefs = extractScreenDefinitions(sourceCode, navFile, projectRoot);
58
-
59
- for (const screenDef of screenDefs) {
60
- if (processedRoutes.has(screenDef.routeName)) continue;
61
- processedRoutes.add(screenDef.routeName);
62
-
63
- // Read and extract content from the screen component file
64
- if (fs.existsSync(screenDef.filePath)) {
65
- let extracted: any;
66
- if (fileAstCache.has(screenDef.filePath)) {
67
- extracted = fileAstCache.get(screenDef.filePath);
68
- } else {
69
- const screenSource = fs.readFileSync(screenDef.filePath, 'utf-8');
70
- extracted = extractContentFromAST(screenSource, screenDef.filePath);
71
- fileAstCache.set(screenDef.filePath, extracted);
72
- }
73
-
74
- screens.push({
75
- routeName: screenDef.routeName,
76
- filePath: screenDef.filePath,
77
- title: screenDef.title,
78
- description: buildDescription(extracted),
79
- navigationLinks: extracted.navigationLinks,
80
- });
81
- } else {
82
- // Component defined in same file or import not resolved
83
- screens.push({
84
- routeName: screenDef.routeName,
85
- filePath: screenDef.filePath,
86
- title: screenDef.title,
87
- description: 'Screen content',
88
- navigationLinks: [],
89
- });
90
- }
91
- }
92
- }
93
-
94
- return screens;
95
- }
96
-
97
- interface ScreenDefinition {
98
- routeName: string;
99
- componentName: string;
100
- filePath: string;
101
- title?: string;
102
- }
103
-
104
- /**
105
- * Find all files containing navigator creation functions.
106
- */
107
- function findNavigatorFiles(projectRoot: string): string[] {
108
- const result: string[] = [];
109
- const srcDir = path.join(projectRoot, 'src');
110
- const searchDirs = [
111
- fs.existsSync(srcDir) ? srcDir : projectRoot,
112
- ];
113
-
114
- for (const dir of searchDirs) {
115
- walkAndSearch(dir, result, projectRoot);
116
- }
117
-
118
- return result;
119
- }
120
-
121
- function walkAndSearch(dir: string, result: string[], projectRoot: string) {
122
- // Skip common non-source directories
123
- const skipDirs = ['node_modules', '.git', 'lib', 'build', 'dist', '__tests__', '__mocks__', 'android', 'ios'];
124
-
125
- let entries: fs.Dirent[];
126
- try {
127
- entries = fs.readdirSync(dir, { withFileTypes: true });
128
- } catch {
129
- return;
130
- }
131
-
132
- for (const entry of entries) {
133
- const fullPath = path.join(dir, entry.name);
134
-
135
- if (entry.isDirectory()) {
136
- if (skipDirs.includes(entry.name) || entry.name.startsWith('.')) continue;
137
- walkAndSearch(fullPath, result, projectRoot);
138
- continue;
139
- }
140
-
141
- if (!entry.name.match(/\.(tsx?|jsx?)$/)) continue;
142
-
143
- // Quick text search before expensive parsing
144
- const content = fs.readFileSync(fullPath, 'utf-8');
145
- const hasNavigator = NAVIGATOR_FUNCTIONS.some(fn => content.includes(fn));
146
- if (hasNavigator) {
147
- result.push(fullPath);
148
- }
149
- }
150
- }
151
-
152
- /**
153
- * Extract screen definitions from a navigator file.
154
- * Handles both static (v7) and dynamic (v5/v6/v7) patterns.
155
- */
156
- function extractScreenDefinitions(
157
- sourceCode: string,
158
- filePath: string,
159
- projectRoot: string
160
- ): ScreenDefinition[] {
161
- const screens: ScreenDefinition[] = [];
162
- const imports = new Map<string, string>(); // componentName → import path
163
-
164
- let ast: ReturnType<typeof parse>;
165
- try {
166
- ast = parse(sourceCode, {
167
- sourceType: 'module',
168
- plugins: ['jsx', 'typescript', 'decorators-legacy'],
169
- });
170
- } catch {
171
- console.warn(`[generate-map] Failed to parse ${filePath}`);
172
- return screens;
173
- }
174
-
175
- // First pass: collect all imports
176
- traverse(ast, {
177
- ImportDeclaration(nodePath: any) {
178
- const source = nodePath.node.source.value;
179
- for (const specifier of nodePath.node.specifiers) {
180
- if (t.isImportDefaultSpecifier(specifier) || t.isImportSpecifier(specifier)) {
181
- imports.set(specifier.local.name, source);
182
- }
183
- }
184
- },
185
- });
186
-
187
- // Second pass: find screen definitions
188
- traverse(ast, {
189
- // Dynamic config: <Stack.Screen name="Home" component={HomeScreen} />
190
- JSXOpeningElement(nodePath: any) {
191
- const nameNode = nodePath.node.name;
192
- if (!t.isJSXMemberExpression(nameNode)) return;
193
- if (!t.isJSXIdentifier(nameNode.property) || nameNode.property.name !== 'Screen') return;
194
-
195
- let screenName: string | null = null;
196
- let componentName: string | null = null;
197
- let title: string | null = null;
198
-
199
- for (const attr of nodePath.node.attributes) {
200
- if (!t.isJSXAttribute(attr) || !t.isJSXIdentifier(attr.name)) continue;
201
-
202
- if (attr.name.name === 'name') {
203
- if (t.isStringLiteral(attr.value)) {
204
- screenName = attr.value.value;
205
- } else if (t.isJSXExpressionContainer(attr.value)) {
206
- const expr = attr.value.expression;
207
- if (t.isStringLiteral(expr)) {
208
- screenName = expr.value;
209
- } else if (t.isMemberExpression(expr) && t.isIdentifier(expr.property)) {
210
- screenName = expr.property.name;
211
- } else if (t.isIdentifier(expr)) {
212
- screenName = expr.name;
213
- }
214
- }
215
- }
216
-
217
- if (attr.name.name === 'component' && t.isJSXExpressionContainer(attr.value)) {
218
- const expr = attr.value.expression;
219
- if (t.isIdentifier(expr)) {
220
- componentName = expr.name;
221
- } else if (t.isMemberExpression(expr)) {
222
- if (t.isIdentifier(expr.object) && t.isIdentifier(expr.property)) {
223
- componentName = `${expr.object.name}.${expr.property.name}`;
224
- }
225
- }
226
- }
227
-
228
- if (attr.name.name === 'options' && t.isJSXExpressionContainer(attr.value)) {
229
- title = extractTitleFromOptions(attr.value.expression);
230
- }
231
- }
232
-
233
- console.log(`[DEBUG-AST-Raw] Checked Screen. screenName: ${screenName}, componentName: ${componentName}`);
234
-
235
- if (screenName && componentName) {
236
- console.log(`[DEBUG-AST] Found Dynamic Screen: ${screenName} -> component: ${componentName}`);
237
- screens.push({
238
- routeName: screenName,
239
- componentName,
240
- filePath: resolveComponentPath(componentName, imports, filePath, projectRoot),
241
- title: title || undefined,
242
- });
243
- }
244
- },
245
-
246
- // Static config (v7): createNativeStackNavigator({ screens: { Home: HomeScreen } })
247
- CallExpression(nodePath: any) {
248
- const callee = nodePath.node.callee;
249
- if (!t.isIdentifier(callee)) return;
250
- if (!NAVIGATOR_FUNCTIONS.includes(callee.name)) return;
251
-
252
- const firstArg = nodePath.node.arguments[0];
253
- if (!t.isObjectExpression(firstArg)) return;
254
-
255
- // Find the 'screens' property
256
- for (const prop of firstArg.properties) {
257
- if (!t.isObjectProperty(prop)) continue;
258
- if (!t.isIdentifier(prop.key) || prop.key.name !== 'screens') continue;
259
- if (!t.isObjectExpression(prop.value)) continue;
260
-
261
- for (const screenProp of prop.value.properties) {
262
- if (!t.isObjectProperty(screenProp)) continue;
263
-
264
- let screenName: string | null = null;
265
-
266
- if (!screenProp.computed) {
267
- if (t.isIdentifier(screenProp.key)) screenName = screenProp.key.name;
268
- else if (t.isStringLiteral(screenProp.key)) screenName = screenProp.key.value;
269
- } else {
270
- // Calculated key: [StackNav.Home]: HomeScreen
271
- if (t.isIdentifier(screenProp.key)) screenName = screenProp.key.name;
272
- else if (t.isMemberExpression(screenProp.key) && t.isIdentifier(screenProp.key.property)) {
273
- screenName = screenProp.key.property.name;
274
- }
275
- }
276
-
277
- if (!screenName) continue;
278
-
279
- let componentName: string | null = null;
280
- let title: string | undefined;
281
-
282
- // Simple: Home: HomeScreen (or StackRoute.HomeScreen)
283
- if (t.isIdentifier(screenProp.value)) {
284
- componentName = screenProp.value.name;
285
- } else if (t.isMemberExpression(screenProp.value)) {
286
- if (t.isIdentifier(screenProp.value.object) && t.isIdentifier(screenProp.value.property)) {
287
- componentName = `${screenProp.value.object.name}.${screenProp.value.property.name}`;
288
- }
289
- }
290
-
291
- // Object: Home: { screen: HomeScreen, options: { title: 'Home' } }
292
- if (t.isObjectExpression(screenProp.value)) {
293
- for (const inner of screenProp.value.properties) {
294
- if (!t.isObjectProperty(inner) || !t.isIdentifier(inner.key)) continue;
295
-
296
- if (inner.key.name === 'screen' && t.isIdentifier(inner.value)) {
297
- componentName = inner.value.name;
298
- }
299
- if (inner.key.name === 'options') {
300
- title = extractTitleFromOptions(inner.value) || undefined;
301
- }
302
- }
303
- }
304
-
305
- if (componentName) {
306
- screens.push({
307
- routeName: screenName,
308
- componentName,
309
- filePath: resolveComponentPath(componentName, imports, filePath, projectRoot),
310
- title,
311
- });
312
- }
313
- }
314
- }
315
- },
316
- });
317
-
318
- return screens;
319
- }
320
-
321
- function extractTitleFromOptions(optionsNode: any): string | null {
322
- if (!t.isObjectExpression(optionsNode)) return null;
323
-
324
- for (const prop of optionsNode.properties) {
325
- if (
326
- t.isObjectProperty(prop) &&
327
- t.isIdentifier(prop.key) &&
328
- prop.key.name === 'title' &&
329
- t.isStringLiteral(prop.value)
330
- ) {
331
- return prop.value.value;
332
- }
333
- }
334
- return null;
335
- }
336
-
337
- /**
338
- * Resolve a component name to its source file path via imports.
339
- * Also handles dot-notation intermediate tracing (e.g., StackRoute.Login)
340
- */
341
- function resolveComponentPath(
342
- componentName: string,
343
- imports: Map<string, string>,
344
- currentFile: string,
345
- _projectRoot: string
346
- ): string {
347
- const parts = componentName.split('.');
348
- const baseComponent: string | undefined = parts[0];
349
- const property: string | undefined = parts[1];
350
-
351
- if (!baseComponent) return currentFile;
352
-
353
- const importPath = imports.get(baseComponent);
354
- if (!importPath) return currentFile;
355
-
356
- let resolvedBase = currentFile;
357
- if (importPath.startsWith('.')) {
358
- const dir = path.dirname(currentFile);
359
- const resolved = path.resolve(dir, importPath);
360
-
361
- const extensions = ['.tsx', '.ts', '.jsx', '.js'];
362
- let found = false;
363
- for (const ext of extensions) {
364
- if (fs.existsSync(resolved + ext)) {
365
- resolvedBase = resolved + ext;
366
- found = true;
367
- break;
368
- }
369
- }
370
- if (!found) {
371
- for (const ext of extensions) {
372
- const indexPath = path.join(resolved, `index${ext}`);
373
- if (fs.existsSync(indexPath)) {
374
- resolvedBase = indexPath;
375
- found = true;
376
- break;
377
- }
378
- }
379
- }
380
- if (!found) resolvedBase = resolved;
381
- }
382
-
383
- if (!property || resolvedBase === currentFile) return resolvedBase;
384
-
385
- return traceExportProperty(resolvedBase, baseComponent, property) || resolvedBase;
386
- }
387
-
388
- /**
389
- * Traces an exported object property through an intermediate file to its deep source file.
390
- */
391
- function traceExportProperty(filePath: string, objectName: string, propertyName: string): string | null {
392
- if (!fs.existsSync(filePath)) return null;
393
- const sourceCode = fs.readFileSync(filePath, 'utf-8');
394
- let ast: ReturnType<typeof parse>;
395
- try {
396
- ast = parse(sourceCode, { sourceType: 'module', plugins: ['jsx', 'typescript', 'decorators-legacy'] });
397
- } catch { return null; }
398
-
399
- const innerImports = new Map<string, string>();
400
- let targetIdentifier: string | null = null;
401
-
402
- traverse(ast, {
403
- ImportDeclaration(nodePath: any) {
404
- const source = nodePath.node.source.value;
405
- for (const specifier of nodePath.node.specifiers) {
406
- if (t.isImportDefaultSpecifier(specifier) || t.isImportSpecifier(specifier)) {
407
- innerImports.set(specifier.local.name, source);
408
- }
409
- }
410
- },
411
- VariableDeclarator(nodePath: any) {
412
- if (t.isIdentifier(nodePath.node.id) && nodePath.node.id.name === objectName) {
413
- if (t.isObjectExpression(nodePath.node.init)) {
414
- for (const prop of nodePath.node.init.properties) {
415
- if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
416
- const keyName = prop.key.name;
417
- if (keyName === propertyName) {
418
- if (t.isIdentifier(prop.value)) {
419
- targetIdentifier = prop.value.name;
420
- }
421
- }
422
- }
423
- }
424
- }
425
- }
426
- }
427
- });
428
-
429
- if (!targetIdentifier) return null;
430
-
431
- const importPath = innerImports.get(targetIdentifier);
432
- if (!importPath || !importPath.startsWith('.')) return null;
433
-
434
- const dir = path.dirname(filePath);
435
- const resolved = path.resolve(dir, importPath);
436
- const extensions = ['.tsx', '.ts', '.jsx', '.js'];
437
- for (const ext of extensions) {
438
- if (fs.existsSync(resolved + ext)) return resolved + ext;
439
- }
440
- for (const ext of extensions) {
441
- const indexPath = path.join(resolved, `index${ext}`);
442
- if (fs.existsSync(indexPath)) return indexPath;
443
- }
444
- return resolved;
445
- }