@mobileai/react-native 0.9.17 → 0.9.18

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 (213) hide show
  1. package/package.json +2 -5
  2. package/lib/module/__cli_tmp__.js.map +0 -1
  3. package/lib/module/components/AIAgent.js.map +0 -1
  4. package/lib/module/components/AIZone.js.map +0 -1
  5. package/lib/module/components/AgentChatBar.js.map +0 -1
  6. package/lib/module/components/AgentErrorBoundary.js.map +0 -1
  7. package/lib/module/components/AgentOverlay.js.map +0 -1
  8. package/lib/module/components/DiscoveryTooltip.js.map +0 -1
  9. package/lib/module/components/HighlightOverlay.js.map +0 -1
  10. package/lib/module/components/Icons.js.map +0 -1
  11. package/lib/module/components/ProactiveHint.js.map +0 -1
  12. package/lib/module/components/cards/InfoCard.js.map +0 -1
  13. package/lib/module/components/cards/ReviewSummary.js.map +0 -1
  14. package/lib/module/config/endpoints.js.map +0 -1
  15. package/lib/module/core/ActionRegistry.js.map +0 -1
  16. package/lib/module/core/AgentRuntime.js.map +0 -1
  17. package/lib/module/core/FiberTreeWalker.js.map +0 -1
  18. package/lib/module/core/IdleDetector.js.map +0 -1
  19. package/lib/module/core/MCPBridge.js.map +0 -1
  20. package/lib/module/core/ScreenDehydrator.js.map +0 -1
  21. package/lib/module/core/ZoneRegistry.js.map +0 -1
  22. package/lib/module/core/systemPrompt.js.map +0 -1
  23. package/lib/module/core/types.js.map +0 -1
  24. package/lib/module/hooks/useAction.js.map +0 -1
  25. package/lib/module/index.js.map +0 -1
  26. package/lib/module/plugin/withAppIntents.js.map +0 -1
  27. package/lib/module/providers/GeminiProvider.js.map +0 -1
  28. package/lib/module/providers/OpenAIProvider.js.map +0 -1
  29. package/lib/module/providers/ProviderFactory.js.map +0 -1
  30. package/lib/module/services/AudioInputService.js.map +0 -1
  31. package/lib/module/services/AudioOutputService.js.map +0 -1
  32. package/lib/module/services/KnowledgeBaseService.js.map +0 -1
  33. package/lib/module/services/VoiceService.js.map +0 -1
  34. package/lib/module/services/flags/FlagService.js.map +0 -1
  35. package/lib/module/services/telemetry/MobileAI.js.map +0 -1
  36. package/lib/module/services/telemetry/PiiScrubber.js.map +0 -1
  37. package/lib/module/services/telemetry/TelemetryService.js.map +0 -1
  38. package/lib/module/services/telemetry/TouchAutoCapture.js.map +0 -1
  39. package/lib/module/services/telemetry/device.js.map +0 -1
  40. package/lib/module/services/telemetry/deviceMetadata.js.map +0 -1
  41. package/lib/module/services/telemetry/index.js.map +0 -1
  42. package/lib/module/services/telemetry/types.js.map +0 -1
  43. package/lib/module/support/CSATSurvey.js.map +0 -1
  44. package/lib/module/support/EscalationEventSource.js.map +0 -1
  45. package/lib/module/support/EscalationSocket.js.map +0 -1
  46. package/lib/module/support/SupportChatModal.js.map +0 -1
  47. package/lib/module/support/SupportGreeting.js.map +0 -1
  48. package/lib/module/support/TicketStore.js.map +0 -1
  49. package/lib/module/support/escalateTool.js.map +0 -1
  50. package/lib/module/support/index.js.map +0 -1
  51. package/lib/module/support/supportPrompt.js.map +0 -1
  52. package/lib/module/support/types.js.map +0 -1
  53. package/lib/module/tools/datePickerTool.js.map +0 -1
  54. package/lib/module/tools/guideTool.js.map +0 -1
  55. package/lib/module/tools/index.js.map +0 -1
  56. package/lib/module/tools/keyboardTool.js.map +0 -1
  57. package/lib/module/tools/longPressTool.js.map +0 -1
  58. package/lib/module/tools/pickerTool.js.map +0 -1
  59. package/lib/module/tools/restoreTool.js.map +0 -1
  60. package/lib/module/tools/scrollTool.js.map +0 -1
  61. package/lib/module/tools/simplifyTool.js.map +0 -1
  62. package/lib/module/tools/sliderTool.js.map +0 -1
  63. package/lib/module/tools/tapTool.js.map +0 -1
  64. package/lib/module/tools/typeTool.js.map +0 -1
  65. package/lib/module/tools/types.js.map +0 -1
  66. package/lib/module/types/jsx.d.js.map +0 -1
  67. package/lib/module/utils/audioUtils.js.map +0 -1
  68. package/lib/module/utils/logger.js.map +0 -1
  69. package/lib/typescript/babel.config.d.ts.map +0 -1
  70. package/lib/typescript/bin/generate-map.d.cts.map +0 -1
  71. package/lib/typescript/eslint.config.d.mts.map +0 -1
  72. package/lib/typescript/generate-map.d.ts.map +0 -1
  73. package/lib/typescript/src/__cli_tmp__.d.ts.map +0 -1
  74. package/lib/typescript/src/components/AIAgent.d.ts.map +0 -1
  75. package/lib/typescript/src/components/AIZone.d.ts.map +0 -1
  76. package/lib/typescript/src/components/AgentChatBar.d.ts.map +0 -1
  77. package/lib/typescript/src/components/AgentErrorBoundary.d.ts.map +0 -1
  78. package/lib/typescript/src/components/AgentOverlay.d.ts.map +0 -1
  79. package/lib/typescript/src/components/DiscoveryTooltip.d.ts.map +0 -1
  80. package/lib/typescript/src/components/HighlightOverlay.d.ts.map +0 -1
  81. package/lib/typescript/src/components/Icons.d.ts.map +0 -1
  82. package/lib/typescript/src/components/ProactiveHint.d.ts.map +0 -1
  83. package/lib/typescript/src/components/cards/InfoCard.d.ts.map +0 -1
  84. package/lib/typescript/src/components/cards/ReviewSummary.d.ts.map +0 -1
  85. package/lib/typescript/src/config/endpoints.d.ts.map +0 -1
  86. package/lib/typescript/src/core/ActionRegistry.d.ts.map +0 -1
  87. package/lib/typescript/src/core/AgentRuntime.d.ts.map +0 -1
  88. package/lib/typescript/src/core/FiberTreeWalker.d.ts.map +0 -1
  89. package/lib/typescript/src/core/IdleDetector.d.ts.map +0 -1
  90. package/lib/typescript/src/core/MCPBridge.d.ts.map +0 -1
  91. package/lib/typescript/src/core/ScreenDehydrator.d.ts.map +0 -1
  92. package/lib/typescript/src/core/ZoneRegistry.d.ts.map +0 -1
  93. package/lib/typescript/src/core/systemPrompt.d.ts.map +0 -1
  94. package/lib/typescript/src/core/types.d.ts.map +0 -1
  95. package/lib/typescript/src/hooks/useAction.d.ts.map +0 -1
  96. package/lib/typescript/src/index.d.ts.map +0 -1
  97. package/lib/typescript/src/plugin/withAppIntents.d.ts.map +0 -1
  98. package/lib/typescript/src/providers/GeminiProvider.d.ts.map +0 -1
  99. package/lib/typescript/src/providers/OpenAIProvider.d.ts.map +0 -1
  100. package/lib/typescript/src/providers/ProviderFactory.d.ts.map +0 -1
  101. package/lib/typescript/src/services/AudioInputService.d.ts.map +0 -1
  102. package/lib/typescript/src/services/AudioOutputService.d.ts.map +0 -1
  103. package/lib/typescript/src/services/KnowledgeBaseService.d.ts.map +0 -1
  104. package/lib/typescript/src/services/VoiceService.d.ts.map +0 -1
  105. package/lib/typescript/src/services/flags/FlagService.d.ts.map +0 -1
  106. package/lib/typescript/src/services/telemetry/MobileAI.d.ts.map +0 -1
  107. package/lib/typescript/src/services/telemetry/PiiScrubber.d.ts.map +0 -1
  108. package/lib/typescript/src/services/telemetry/TelemetryService.d.ts.map +0 -1
  109. package/lib/typescript/src/services/telemetry/TouchAutoCapture.d.ts.map +0 -1
  110. package/lib/typescript/src/services/telemetry/device.d.ts.map +0 -1
  111. package/lib/typescript/src/services/telemetry/deviceMetadata.d.ts.map +0 -1
  112. package/lib/typescript/src/services/telemetry/index.d.ts.map +0 -1
  113. package/lib/typescript/src/services/telemetry/types.d.ts.map +0 -1
  114. package/lib/typescript/src/support/CSATSurvey.d.ts.map +0 -1
  115. package/lib/typescript/src/support/EscalationEventSource.d.ts.map +0 -1
  116. package/lib/typescript/src/support/EscalationSocket.d.ts.map +0 -1
  117. package/lib/typescript/src/support/SupportChatModal.d.ts.map +0 -1
  118. package/lib/typescript/src/support/SupportGreeting.d.ts.map +0 -1
  119. package/lib/typescript/src/support/TicketStore.d.ts.map +0 -1
  120. package/lib/typescript/src/support/escalateTool.d.ts.map +0 -1
  121. package/lib/typescript/src/support/index.d.ts.map +0 -1
  122. package/lib/typescript/src/support/supportPrompt.d.ts.map +0 -1
  123. package/lib/typescript/src/support/types.d.ts.map +0 -1
  124. package/lib/typescript/src/tools/datePickerTool.d.ts.map +0 -1
  125. package/lib/typescript/src/tools/guideTool.d.ts.map +0 -1
  126. package/lib/typescript/src/tools/index.d.ts.map +0 -1
  127. package/lib/typescript/src/tools/keyboardTool.d.ts.map +0 -1
  128. package/lib/typescript/src/tools/longPressTool.d.ts.map +0 -1
  129. package/lib/typescript/src/tools/pickerTool.d.ts.map +0 -1
  130. package/lib/typescript/src/tools/restoreTool.d.ts.map +0 -1
  131. package/lib/typescript/src/tools/scrollTool.d.ts.map +0 -1
  132. package/lib/typescript/src/tools/simplifyTool.d.ts.map +0 -1
  133. package/lib/typescript/src/tools/sliderTool.d.ts.map +0 -1
  134. package/lib/typescript/src/tools/tapTool.d.ts.map +0 -1
  135. package/lib/typescript/src/tools/typeTool.d.ts.map +0 -1
  136. package/lib/typescript/src/tools/types.d.ts.map +0 -1
  137. package/lib/typescript/src/utils/audioUtils.d.ts.map +0 -1
  138. package/lib/typescript/src/utils/logger.d.ts.map +0 -1
  139. package/src/__cli_tmp__.tsx +0 -9
  140. package/src/cli/analyzers/chain-analyzer.ts +0 -183
  141. package/src/cli/extractors/ai-extractor.ts +0 -6
  142. package/src/cli/extractors/ast-extractor.ts +0 -551
  143. package/src/cli/generate-intents.ts +0 -140
  144. package/src/cli/generate-map.ts +0 -121
  145. package/src/cli/generate-swift.ts +0 -116
  146. package/src/cli/scanners/expo-scanner.ts +0 -203
  147. package/src/cli/scanners/rn-scanner.ts +0 -445
  148. package/src/components/AIAgent.tsx +0 -1716
  149. package/src/components/AIZone.tsx +0 -147
  150. package/src/components/AgentChatBar.tsx +0 -1143
  151. package/src/components/AgentErrorBoundary.tsx +0 -78
  152. package/src/components/AgentOverlay.tsx +0 -73
  153. package/src/components/DiscoveryTooltip.tsx +0 -148
  154. package/src/components/HighlightOverlay.tsx +0 -136
  155. package/src/components/Icons.tsx +0 -253
  156. package/src/components/ProactiveHint.tsx +0 -145
  157. package/src/components/cards/InfoCard.tsx +0 -58
  158. package/src/components/cards/ReviewSummary.tsx +0 -76
  159. package/src/config/endpoints.ts +0 -22
  160. package/src/core/ActionRegistry.ts +0 -105
  161. package/src/core/AgentRuntime.ts +0 -1471
  162. package/src/core/FiberTreeWalker.ts +0 -930
  163. package/src/core/IdleDetector.ts +0 -72
  164. package/src/core/MCPBridge.ts +0 -163
  165. package/src/core/ScreenDehydrator.ts +0 -53
  166. package/src/core/ZoneRegistry.ts +0 -44
  167. package/src/core/systemPrompt.ts +0 -431
  168. package/src/core/types.ts +0 -521
  169. package/src/hooks/useAction.ts +0 -182
  170. package/src/index.ts +0 -83
  171. package/src/plugin/withAppIntents.ts +0 -98
  172. package/src/providers/GeminiProvider.ts +0 -357
  173. package/src/providers/OpenAIProvider.ts +0 -379
  174. package/src/providers/ProviderFactory.ts +0 -36
  175. package/src/services/AudioInputService.ts +0 -226
  176. package/src/services/AudioOutputService.ts +0 -236
  177. package/src/services/KnowledgeBaseService.ts +0 -156
  178. package/src/services/VoiceService.ts +0 -451
  179. package/src/services/flags/FlagService.ts +0 -137
  180. package/src/services/telemetry/MobileAI.ts +0 -66
  181. package/src/services/telemetry/PiiScrubber.ts +0 -17
  182. package/src/services/telemetry/TelemetryService.ts +0 -323
  183. package/src/services/telemetry/TouchAutoCapture.ts +0 -165
  184. package/src/services/telemetry/device.ts +0 -93
  185. package/src/services/telemetry/deviceMetadata.ts +0 -13
  186. package/src/services/telemetry/index.ts +0 -13
  187. package/src/services/telemetry/types.ts +0 -75
  188. package/src/support/CSATSurvey.tsx +0 -304
  189. package/src/support/EscalationEventSource.ts +0 -190
  190. package/src/support/EscalationSocket.ts +0 -152
  191. package/src/support/SupportChatModal.tsx +0 -563
  192. package/src/support/SupportGreeting.tsx +0 -161
  193. package/src/support/TicketStore.ts +0 -100
  194. package/src/support/escalateTool.ts +0 -174
  195. package/src/support/index.ts +0 -29
  196. package/src/support/supportPrompt.ts +0 -55
  197. package/src/support/types.ts +0 -155
  198. package/src/tools/datePickerTool.ts +0 -60
  199. package/src/tools/guideTool.ts +0 -76
  200. package/src/tools/index.ts +0 -20
  201. package/src/tools/keyboardTool.ts +0 -30
  202. package/src/tools/longPressTool.ts +0 -61
  203. package/src/tools/pickerTool.ts +0 -115
  204. package/src/tools/restoreTool.ts +0 -33
  205. package/src/tools/scrollTool.ts +0 -156
  206. package/src/tools/simplifyTool.ts +0 -33
  207. package/src/tools/sliderTool.ts +0 -65
  208. package/src/tools/tapTool.ts +0 -93
  209. package/src/tools/typeTool.ts +0 -113
  210. package/src/tools/types.ts +0 -58
  211. package/src/types/jsx.d.ts +0 -20
  212. package/src/utils/audioUtils.ts +0 -54
  213. 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
- }