@reactgraph/cli 0.1.1

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 (178) hide show
  1. package/README.md +319 -0
  2. package/bun.lock +527 -0
  3. package/dist/cli/components/IndexProgress.d.ts +18 -0
  4. package/dist/cli/components/IndexProgress.d.ts.map +1 -0
  5. package/dist/cli/components/IndexProgress.js +26 -0
  6. package/dist/cli/components/IndexProgress.js.map +1 -0
  7. package/dist/cli/components/InitResult.d.ts +7 -0
  8. package/dist/cli/components/InitResult.d.ts.map +1 -0
  9. package/dist/cli/components/InitResult.js +6 -0
  10. package/dist/cli/components/InitResult.js.map +1 -0
  11. package/dist/cli/index-cmd.d.ts +7 -0
  12. package/dist/cli/index-cmd.d.ts.map +1 -0
  13. package/dist/cli/index-cmd.js +28 -0
  14. package/dist/cli/index-cmd.js.map +1 -0
  15. package/dist/cli/index.d.ts +3 -0
  16. package/dist/cli/index.d.ts.map +1 -0
  17. package/dist/cli/index.js +81 -0
  18. package/dist/cli/index.js.map +1 -0
  19. package/dist/cli/init.d.ts +8 -0
  20. package/dist/cli/init.d.ts.map +1 -0
  21. package/dist/cli/init.js +77 -0
  22. package/dist/cli/init.js.map +1 -0
  23. package/dist/cli/serve.d.ts +2 -0
  24. package/dist/cli/serve.d.ts.map +1 -0
  25. package/dist/cli/serve.js +28 -0
  26. package/dist/cli/serve.js.map +1 -0
  27. package/dist/cli/unused.d.ts +2 -0
  28. package/dist/cli/unused.d.ts.map +1 -0
  29. package/dist/cli/unused.js +56 -0
  30. package/dist/cli/unused.js.map +1 -0
  31. package/dist/graph/graph.d.ts +30 -0
  32. package/dist/graph/graph.d.ts.map +1 -0
  33. package/dist/graph/graph.js +166 -0
  34. package/dist/graph/graph.js.map +1 -0
  35. package/dist/graph/index.d.ts +5 -0
  36. package/dist/graph/index.d.ts.map +1 -0
  37. package/dist/graph/index.js +5 -0
  38. package/dist/graph/index.js.map +1 -0
  39. package/dist/graph/schema.d.ts +33 -0
  40. package/dist/graph/schema.d.ts.map +1 -0
  41. package/dist/graph/schema.js +3 -0
  42. package/dist/graph/schema.js.map +1 -0
  43. package/dist/graph/serialize.d.ts +7 -0
  44. package/dist/graph/serialize.d.ts.map +1 -0
  45. package/dist/graph/serialize.js +39 -0
  46. package/dist/graph/serialize.js.map +1 -0
  47. package/dist/graph/traverse.d.ts +14 -0
  48. package/dist/graph/traverse.d.ts.map +1 -0
  49. package/dist/graph/traverse.js +50 -0
  50. package/dist/graph/traverse.js.map +1 -0
  51. package/dist/mcp/formatter.d.ts +26 -0
  52. package/dist/mcp/formatter.d.ts.map +1 -0
  53. package/dist/mcp/formatter.js +691 -0
  54. package/dist/mcp/formatter.js.map +1 -0
  55. package/dist/mcp/server.d.ts +2 -0
  56. package/dist/mcp/server.d.ts.map +1 -0
  57. package/dist/mcp/server.js +45 -0
  58. package/dist/mcp/server.js.map +1 -0
  59. package/dist/mcp/tools.d.ts +9 -0
  60. package/dist/mcp/tools.d.ts.map +1 -0
  61. package/dist/mcp/tools.js +136 -0
  62. package/dist/mcp/tools.js.map +1 -0
  63. package/dist/output/ai-context.d.ts +7 -0
  64. package/dist/output/ai-context.d.ts.map +1 -0
  65. package/dist/output/ai-context.js +26 -0
  66. package/dist/output/ai-context.js.map +1 -0
  67. package/dist/parser/extractors/api-calls.d.ts +15 -0
  68. package/dist/parser/extractors/api-calls.d.ts.map +1 -0
  69. package/dist/parser/extractors/api-calls.js +168 -0
  70. package/dist/parser/extractors/api-calls.js.map +1 -0
  71. package/dist/parser/extractors/components.d.ts +5 -0
  72. package/dist/parser/extractors/components.d.ts.map +1 -0
  73. package/dist/parser/extractors/components.js +236 -0
  74. package/dist/parser/extractors/components.js.map +1 -0
  75. package/dist/parser/extractors/context.d.ts +14 -0
  76. package/dist/parser/extractors/context.d.ts.map +1 -0
  77. package/dist/parser/extractors/context.js +196 -0
  78. package/dist/parser/extractors/context.js.map +1 -0
  79. package/dist/parser/extractors/effects.d.ts +14 -0
  80. package/dist/parser/extractors/effects.d.ts.map +1 -0
  81. package/dist/parser/extractors/effects.js +175 -0
  82. package/dist/parser/extractors/effects.js.map +1 -0
  83. package/dist/parser/extractors/hooks.d.ts +5 -0
  84. package/dist/parser/extractors/hooks.d.ts.map +1 -0
  85. package/dist/parser/extractors/hooks.js +242 -0
  86. package/dist/parser/extractors/hooks.js.map +1 -0
  87. package/dist/parser/extractors/imports.d.ts +6 -0
  88. package/dist/parser/extractors/imports.d.ts.map +1 -0
  89. package/dist/parser/extractors/imports.js +148 -0
  90. package/dist/parser/extractors/imports.js.map +1 -0
  91. package/dist/parser/extractors/index.d.ts +12 -0
  92. package/dist/parser/extractors/index.d.ts.map +1 -0
  93. package/dist/parser/extractors/index.js +11 -0
  94. package/dist/parser/extractors/index.js.map +1 -0
  95. package/dist/parser/extractors/jsx-tree.d.ts +5 -0
  96. package/dist/parser/extractors/jsx-tree.d.ts.map +1 -0
  97. package/dist/parser/extractors/jsx-tree.js +226 -0
  98. package/dist/parser/extractors/jsx-tree.js.map +1 -0
  99. package/dist/parser/extractors/routes.d.ts +13 -0
  100. package/dist/parser/extractors/routes.d.ts.map +1 -0
  101. package/dist/parser/extractors/routes.js +275 -0
  102. package/dist/parser/extractors/routes.js.map +1 -0
  103. package/dist/parser/extractors/state.d.ts +14 -0
  104. package/dist/parser/extractors/state.d.ts.map +1 -0
  105. package/dist/parser/extractors/state.js +368 -0
  106. package/dist/parser/extractors/state.js.map +1 -0
  107. package/dist/parser/extractors/types.d.ts +22 -0
  108. package/dist/parser/extractors/types.d.ts.map +1 -0
  109. package/dist/parser/extractors/types.js +51 -0
  110. package/dist/parser/extractors/types.js.map +1 -0
  111. package/dist/parser/indexer.d.ts +14 -0
  112. package/dist/parser/indexer.d.ts.map +1 -0
  113. package/dist/parser/indexer.js +167 -0
  114. package/dist/parser/indexer.js.map +1 -0
  115. package/dist/parser/pipeline.d.ts +16 -0
  116. package/dist/parser/pipeline.d.ts.map +1 -0
  117. package/dist/parser/pipeline.js +63 -0
  118. package/dist/parser/pipeline.js.map +1 -0
  119. package/dist/parser/setup.d.ts +4 -0
  120. package/dist/parser/setup.d.ts.map +1 -0
  121. package/dist/parser/setup.js +29 -0
  122. package/dist/parser/setup.js.map +1 -0
  123. package/dist/parser/walker.d.ts +6 -0
  124. package/dist/parser/walker.d.ts.map +1 -0
  125. package/dist/parser/walker.js +45 -0
  126. package/dist/parser/walker.js.map +1 -0
  127. package/dist/watcher.d.ts +12 -0
  128. package/dist/watcher.d.ts.map +1 -0
  129. package/dist/watcher.js +72 -0
  130. package/dist/watcher.js.map +1 -0
  131. package/package.json +51 -0
  132. package/src/cli/components/IndexProgress.tsx +79 -0
  133. package/src/cli/components/InitResult.tsx +28 -0
  134. package/src/cli/index-cmd.ts +41 -0
  135. package/src/cli/index.ts +92 -0
  136. package/src/cli/init.ts +97 -0
  137. package/src/cli/serve.ts +29 -0
  138. package/src/cli/unused.ts +88 -0
  139. package/src/graph/graph.ts +179 -0
  140. package/src/graph/index.ts +4 -0
  141. package/src/graph/schema.ts +68 -0
  142. package/src/graph/serialize.ts +40 -0
  143. package/src/graph/traverse.ts +66 -0
  144. package/src/mcp/formatter.ts +757 -0
  145. package/src/mcp/server.ts +59 -0
  146. package/src/mcp/tools.ts +154 -0
  147. package/src/output/ai-context.ts +29 -0
  148. package/src/parser/extractors/api-calls.ts +192 -0
  149. package/src/parser/extractors/components.ts +273 -0
  150. package/src/parser/extractors/context.ts +216 -0
  151. package/src/parser/extractors/effects.ts +205 -0
  152. package/src/parser/extractors/hooks.ts +268 -0
  153. package/src/parser/extractors/imports.ts +192 -0
  154. package/src/parser/extractors/index.ts +11 -0
  155. package/src/parser/extractors/jsx-tree.ts +271 -0
  156. package/src/parser/extractors/routes.ts +331 -0
  157. package/src/parser/extractors/state.ts +392 -0
  158. package/src/parser/extractors/types.ts +71 -0
  159. package/src/parser/indexer.ts +197 -0
  160. package/src/parser/pipeline.ts +89 -0
  161. package/src/parser/setup.ts +33 -0
  162. package/src/parser/walker.ts +61 -0
  163. package/src/watcher.ts +91 -0
  164. package/templates/CLAUDE.md +7 -0
  165. package/tests/extractors.test.ts +164 -0
  166. package/tests/fixtures/basic/src/App.tsx +12 -0
  167. package/tests/fixtures/basic/src/components/Dashboard.tsx +24 -0
  168. package/tests/fixtures/basic/src/components/MetricsCard.tsx +15 -0
  169. package/tests/fixtures/basic/src/components/Sidebar.tsx +20 -0
  170. package/tests/fixtures/basic/src/contexts/ThemeContext.tsx +16 -0
  171. package/tests/fixtures/basic/src/hooks/useAuth.ts +25 -0
  172. package/tests/fixtures/basic/src/stores/authStore.ts +15 -0
  173. package/tests/fixtures/basic/src/utils.ts +7 -0
  174. package/tests/graph.test.ts +91 -0
  175. package/tests/phase2.test.ts +309 -0
  176. package/tests/smoke.test.ts +77 -0
  177. package/tsconfig.json +20 -0
  178. package/vitest.config.ts +8 -0
@@ -0,0 +1,368 @@
1
+ import { nodeId, findAll, findEnclosingFunction } from './types.js';
2
+ /**
3
+ * State management extractor — detects Zustand, Redux Toolkit, Jotai, and Recoil stores.
4
+ *
5
+ * Creation patterns:
6
+ * Zustand: const useStore = create((set) => ({ ... }))
7
+ * Redux: const slice = createSlice({ name, initialState, reducers })
8
+ * Jotai: const atom = atom(defaultValue)
9
+ * Recoil: const state = atom({ key, default })
10
+ */
11
+ export function extractState(tree, filePath, sourceCode, existingNodes) {
12
+ const nodes = [];
13
+ const edges = [];
14
+ const root = tree.rootNode;
15
+ // Build function map for edge sources
16
+ const functionNodes = new Map();
17
+ for (const n of existingNodes) {
18
+ if (n.file === filePath && (n.kind === 'Component' || n.kind === 'Hook')) {
19
+ functionNodes.set(n.name, n);
20
+ }
21
+ }
22
+ // Pass 1: Detect store definitions
23
+ const storeNames = new Map();
24
+ for (let i = 0; i < root.childCount; i++) {
25
+ const child = root.child(i);
26
+ const store = detectStoreCreation(child, filePath);
27
+ if (store) {
28
+ nodes.push(store);
29
+ storeNames.set(store.name, { id: store.id, library: store.meta.library });
30
+ }
31
+ if (child.type === 'export_statement') {
32
+ for (let j = 0; j < child.childCount; j++) {
33
+ const store2 = detectStoreCreation(child.child(j), filePath);
34
+ if (store2) {
35
+ store2.exportType = child.text.startsWith('export default') ? 'default' : 'named';
36
+ nodes.push(store2);
37
+ storeNames.set(store2.name, { id: store2.id, library: store2.meta.library });
38
+ }
39
+ }
40
+ }
41
+ }
42
+ // Also build a map of stores from other files (via existingNodes)
43
+ for (const n of existingNodes) {
44
+ if (n.kind === 'Store' && !storeNames.has(n.name)) {
45
+ storeNames.set(n.name, { id: n.id, library: n.meta.library ?? 'unknown' });
46
+ }
47
+ }
48
+ // Pass 2: Detect reads/writes in components and hooks
49
+ const callExprs = findAll(root, 'call_expression');
50
+ for (const call of callExprs) {
51
+ const callee = call.childForFieldName('function');
52
+ if (!callee)
53
+ continue;
54
+ const enclosingFn = findEnclosingFunction(call);
55
+ if (!enclosingFn)
56
+ continue;
57
+ const enclosingName = getFunctionName(enclosingFn);
58
+ if (!enclosingName)
59
+ continue;
60
+ const enclosingNode = functionNodes.get(enclosingName);
61
+ if (!enclosingNode)
62
+ continue;
63
+ // Zustand: useAuthStore() or useAuthStore(selector)
64
+ const calleeName = callee.type === 'identifier' ? callee.text : null;
65
+ if (calleeName && storeNames.has(calleeName)) {
66
+ const store = storeNames.get(calleeName);
67
+ edges.push({
68
+ source: enclosingNode.id,
69
+ target: store.id,
70
+ kind: 'reads_store',
71
+ meta: { library: store.library },
72
+ });
73
+ continue;
74
+ }
75
+ // Zustand: useAuthStore.getState() — reads
76
+ if (callee.type === 'member_expression') {
77
+ const obj = callee.childForFieldName('object');
78
+ const prop = callee.childForFieldName('property');
79
+ if (obj && prop) {
80
+ const objName = obj.text;
81
+ if (storeNames.has(objName)) {
82
+ const store = storeNames.get(objName);
83
+ if (prop.text === 'getState') {
84
+ edges.push({
85
+ source: enclosingNode.id,
86
+ target: store.id,
87
+ kind: 'reads_store',
88
+ meta: { library: store.library, method: 'getState' },
89
+ });
90
+ }
91
+ else if (prop.text === 'setState') {
92
+ edges.push({
93
+ source: enclosingNode.id,
94
+ target: store.id,
95
+ kind: 'writes_store',
96
+ meta: { library: store.library, method: 'setState' },
97
+ });
98
+ }
99
+ continue;
100
+ }
101
+ }
102
+ }
103
+ // Redux: useSelector(selector)
104
+ if (calleeName === 'useSelector') {
105
+ // Try to find which slice via the selector argument
106
+ const args = call.childForFieldName('arguments');
107
+ const selectorText = args?.child(1)?.text ?? '';
108
+ // Find matching store by checking if selector references store name
109
+ for (const [name, store] of storeNames) {
110
+ if (store.library === 'redux' && selectorText.includes(name.replace('Slice', ''))) {
111
+ edges.push({
112
+ source: enclosingNode.id,
113
+ target: store.id,
114
+ kind: 'reads_store',
115
+ meta: { library: 'redux', selector: selectorText },
116
+ });
117
+ }
118
+ }
119
+ // If no specific store found, create a generic edge
120
+ if (!edges.some(e => e.source === enclosingNode.id && e.kind === 'reads_store')) {
121
+ edges.push({
122
+ source: enclosingNode.id,
123
+ target: 'unresolved:redux-store',
124
+ kind: 'reads_store',
125
+ meta: { library: 'redux', selector: selectorText },
126
+ });
127
+ }
128
+ continue;
129
+ }
130
+ // Redux: useDispatch() — we track dispatch calls separately
131
+ // The actual writes happen when dispatch(action()) is called
132
+ // Jotai: useAtom(atom), useAtomValue(atom), useSetAtom(atom)
133
+ if (calleeName === 'useAtom' || calleeName === 'useAtomValue' || calleeName === 'useSetAtom') {
134
+ const args = call.childForFieldName('arguments');
135
+ const atomArg = args?.child(1);
136
+ if (atomArg) {
137
+ const atomName = atomArg.text;
138
+ const store = storeNames.get(atomName);
139
+ const targetId = store?.id ?? `unresolved:${atomName}`;
140
+ if (calleeName === 'useSetAtom') {
141
+ edges.push({
142
+ source: enclosingNode.id,
143
+ target: targetId,
144
+ kind: 'writes_store',
145
+ meta: { library: 'jotai' },
146
+ });
147
+ }
148
+ else if (calleeName === 'useAtomValue') {
149
+ edges.push({
150
+ source: enclosingNode.id,
151
+ target: targetId,
152
+ kind: 'reads_store',
153
+ meta: { library: 'jotai' },
154
+ });
155
+ }
156
+ else {
157
+ // useAtom — both read and write
158
+ edges.push({
159
+ source: enclosingNode.id,
160
+ target: targetId,
161
+ kind: 'reads_store',
162
+ meta: { library: 'jotai' },
163
+ });
164
+ edges.push({
165
+ source: enclosingNode.id,
166
+ target: targetId,
167
+ kind: 'writes_store',
168
+ meta: { library: 'jotai' },
169
+ });
170
+ }
171
+ }
172
+ continue;
173
+ }
174
+ // Recoil: useRecoilState, useRecoilValue, useSetRecoilState
175
+ if (calleeName === 'useRecoilState' || calleeName === 'useRecoilValue' || calleeName === 'useSetRecoilState') {
176
+ const args = call.childForFieldName('arguments');
177
+ const atomArg = args?.child(1);
178
+ if (atomArg) {
179
+ const atomName = atomArg.text;
180
+ const store = storeNames.get(atomName);
181
+ const targetId = store?.id ?? `unresolved:${atomName}`;
182
+ if (calleeName === 'useSetRecoilState') {
183
+ edges.push({
184
+ source: enclosingNode.id,
185
+ target: targetId,
186
+ kind: 'writes_store',
187
+ meta: { library: 'recoil' },
188
+ });
189
+ }
190
+ else if (calleeName === 'useRecoilValue') {
191
+ edges.push({
192
+ source: enclosingNode.id,
193
+ target: targetId,
194
+ kind: 'reads_store',
195
+ meta: { library: 'recoil' },
196
+ });
197
+ }
198
+ else {
199
+ edges.push({
200
+ source: enclosingNode.id,
201
+ target: targetId,
202
+ kind: 'reads_store',
203
+ meta: { library: 'recoil' },
204
+ });
205
+ edges.push({
206
+ source: enclosingNode.id,
207
+ target: targetId,
208
+ kind: 'writes_store',
209
+ meta: { library: 'recoil' },
210
+ });
211
+ }
212
+ }
213
+ continue;
214
+ }
215
+ }
216
+ return { nodes, edges };
217
+ }
218
+ function detectStoreCreation(node, filePath) {
219
+ if (node.type !== 'lexical_declaration')
220
+ return null;
221
+ const declarator = findDirectChild(node, 'variable_declarator');
222
+ if (!declarator)
223
+ return null;
224
+ const nameNode = declarator.childForFieldName('name');
225
+ const value = declarator.childForFieldName('value');
226
+ if (!nameNode || !value)
227
+ return null;
228
+ if (value.type !== 'call_expression')
229
+ return null;
230
+ const callee = value.childForFieldName('function');
231
+ if (!callee)
232
+ return null;
233
+ const calleeName = callee.text;
234
+ // Zustand: create(...) or create<Type>(...)
235
+ if (calleeName === 'create') {
236
+ const shape = extractObjectShape(value);
237
+ return {
238
+ id: nodeId(filePath, nameNode.text),
239
+ kind: 'Store',
240
+ name: nameNode.text,
241
+ file: filePath,
242
+ line: node.startPosition.row + 1,
243
+ exportType: 'none',
244
+ meta: { library: 'zustand', shape },
245
+ };
246
+ }
247
+ // Redux: createSlice({ name, initialState, reducers })
248
+ if (calleeName === 'createSlice') {
249
+ const shape = extractSliceShape(value);
250
+ return {
251
+ id: nodeId(filePath, nameNode.text),
252
+ kind: 'Store',
253
+ name: nameNode.text,
254
+ file: filePath,
255
+ line: node.startPosition.row + 1,
256
+ exportType: 'none',
257
+ meta: { library: 'redux', shape },
258
+ };
259
+ }
260
+ // Jotai: atom(defaultValue)
261
+ if (calleeName === 'atom') {
262
+ // Distinguish Jotai from Recoil: Recoil's atom takes { key, default }
263
+ const args = value.childForFieldName('arguments');
264
+ const firstArg = args?.child(1);
265
+ const isRecoil = firstArg?.type === 'object' && firstArg.text.includes('key');
266
+ if (isRecoil) {
267
+ return {
268
+ id: nodeId(filePath, nameNode.text),
269
+ kind: 'Store',
270
+ name: nameNode.text,
271
+ file: filePath,
272
+ line: node.startPosition.row + 1,
273
+ exportType: 'none',
274
+ meta: { library: 'recoil' },
275
+ };
276
+ }
277
+ return {
278
+ id: nodeId(filePath, nameNode.text),
279
+ kind: 'Store',
280
+ name: nameNode.text,
281
+ file: filePath,
282
+ line: node.startPosition.row + 1,
283
+ exportType: 'none',
284
+ meta: { library: 'jotai' },
285
+ };
286
+ }
287
+ return null;
288
+ }
289
+ function extractObjectShape(callNode) {
290
+ // Look for the object returned by the zustand creator function
291
+ const args = callNode.childForFieldName('arguments');
292
+ if (!args)
293
+ return [];
294
+ // The first arg to create() is (set) => ({ key1, key2, ... })
295
+ const creator = args.child(1);
296
+ if (!creator)
297
+ return [];
298
+ // Find object or parenthesized_expression containing object
299
+ const objects = findAll(creator, 'object');
300
+ if (objects.length === 0)
301
+ return [];
302
+ const obj = objects[0];
303
+ const keys = [];
304
+ for (let i = 0; i < obj.childCount; i++) {
305
+ const child = obj.child(i);
306
+ if (child.type === 'pair' || child.type === 'method_definition') {
307
+ const key = child.childForFieldName('key') ?? child.childForFieldName('name');
308
+ if (key)
309
+ keys.push(key.text);
310
+ }
311
+ else if (child.type === 'shorthand_property') {
312
+ keys.push(child.text);
313
+ }
314
+ }
315
+ return keys;
316
+ }
317
+ function extractSliceShape(callNode) {
318
+ // createSlice({ initialState: { key1, key2 }, reducers: { ... } })
319
+ const args = callNode.childForFieldName('arguments');
320
+ if (!args)
321
+ return [];
322
+ const configObj = args.child(1);
323
+ if (!configObj || configObj.type !== 'object')
324
+ return [];
325
+ // Find initialState property
326
+ for (let i = 0; i < configObj.childCount; i++) {
327
+ const child = configObj.child(i);
328
+ if (child.type === 'pair') {
329
+ const key = child.childForFieldName('key');
330
+ if (key?.text === 'initialState') {
331
+ const val = child.childForFieldName('value');
332
+ if (val?.type === 'object') {
333
+ const keys = [];
334
+ for (let j = 0; j < val.childCount; j++) {
335
+ const prop = val.child(j);
336
+ if (prop.type === 'pair') {
337
+ const k = prop.childForFieldName('key');
338
+ if (k)
339
+ keys.push(k.text);
340
+ }
341
+ }
342
+ return keys;
343
+ }
344
+ }
345
+ }
346
+ }
347
+ return [];
348
+ }
349
+ function getFunctionName(node) {
350
+ const nameField = node.childForFieldName('name');
351
+ if (nameField)
352
+ return nameField.text;
353
+ if (node.type === 'arrow_function' || node.type === 'function_expression') {
354
+ const parent = node.parent;
355
+ if (parent?.type === 'variable_declarator') {
356
+ return parent.childForFieldName('name')?.text ?? null;
357
+ }
358
+ }
359
+ return null;
360
+ }
361
+ function findDirectChild(node, type) {
362
+ for (let i = 0; i < node.childCount; i++) {
363
+ if (node.child(i).type === type)
364
+ return node.child(i);
365
+ }
366
+ return null;
367
+ }
368
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/parser/extractors/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type Parser from 'tree-sitter';
2
+ import type { GraphNode, GraphEdge } from '../../graph/schema.js';
3
+ export interface ExtractionResult {
4
+ nodes: GraphNode[];
5
+ edges: GraphEdge[];
6
+ }
7
+ export type Extractor = (tree: Parser.Tree, filePath: string, sourceCode: string, existingNodes: GraphNode[]) => ExtractionResult;
8
+ /** Generate a stable node ID from file path and name */
9
+ export declare function nodeId(filePath: string, name: string): string;
10
+ /** Check if a name starts with uppercase (React component convention) */
11
+ export declare function isPascalCase(name: string): boolean;
12
+ /** Check if a name matches hook convention: use + uppercase char */
13
+ export declare function isHookName(name: string): boolean;
14
+ /** Walk all descendants of a tree-sitter node */
15
+ export declare function walkTree(node: Parser.SyntaxNode): Generator<Parser.SyntaxNode>;
16
+ /** Find all descendants matching a type */
17
+ export declare function findAll(node: Parser.SyntaxNode, type: string): Parser.SyntaxNode[];
18
+ /** Find first descendant matching a type */
19
+ export declare function findFirst(node: Parser.SyntaxNode, type: string): Parser.SyntaxNode | null;
20
+ /** Walk up to find the nearest enclosing function/arrow */
21
+ export declare function findEnclosingFunction(node: Parser.SyntaxNode): Parser.SyntaxNode | null;
22
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/parser/extractors/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,MAAM,MAAM,SAAS,GAAG,CACtB,IAAI,EAAE,MAAM,CAAC,IAAI,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,SAAS,EAAE,KACvB,gBAAgB,CAAC;AAEtB,wDAAwD;AACxD,wBAAgB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED,iDAAiD;AACjD,wBAAiB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAK/E;AAED,2CAA2C;AAC3C,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,CAMlF;AAED,4CAA4C;AAC5C,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,GAAG,IAAI,CAKzF;AAED,2DAA2D;AAC3D,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,GAAG,IAAI,CAcvF"}
@@ -0,0 +1,51 @@
1
+ /** Generate a stable node ID from file path and name */
2
+ export function nodeId(filePath, name) {
3
+ return `${filePath}:${name}`;
4
+ }
5
+ /** Check if a name starts with uppercase (React component convention) */
6
+ export function isPascalCase(name) {
7
+ return /^[A-Z]/.test(name);
8
+ }
9
+ /** Check if a name matches hook convention: use + uppercase char */
10
+ export function isHookName(name) {
11
+ return /^use[A-Z]/.test(name);
12
+ }
13
+ /** Walk all descendants of a tree-sitter node */
14
+ export function* walkTree(node) {
15
+ yield node;
16
+ for (let i = 0; i < node.childCount; i++) {
17
+ yield* walkTree(node.child(i));
18
+ }
19
+ }
20
+ /** Find all descendants matching a type */
21
+ export function findAll(node, type) {
22
+ const results = [];
23
+ for (const n of walkTree(node)) {
24
+ if (n.type === type)
25
+ results.push(n);
26
+ }
27
+ return results;
28
+ }
29
+ /** Find first descendant matching a type */
30
+ export function findFirst(node, type) {
31
+ for (const n of walkTree(node)) {
32
+ if (n.type === type)
33
+ return n;
34
+ }
35
+ return null;
36
+ }
37
+ /** Walk up to find the nearest enclosing function/arrow */
38
+ export function findEnclosingFunction(node) {
39
+ let current = node.parent;
40
+ while (current) {
41
+ if (current.type === 'function_declaration' ||
42
+ current.type === 'arrow_function' ||
43
+ current.type === 'function_expression' ||
44
+ current.type === 'method_definition') {
45
+ return current;
46
+ }
47
+ current = current.parent;
48
+ }
49
+ return null;
50
+ }
51
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/parser/extractors/types.ts"],"names":[],"mappings":"AAeA,wDAAwD;AACxD,MAAM,UAAU,MAAM,CAAC,QAAgB,EAAE,IAAY;IACnD,OAAO,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,iDAAiD;AACjD,MAAM,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAuB;IAC/C,MAAM,IAAI,CAAC;IACX,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,OAAO,CAAC,IAAuB,EAAE,IAAY;IAC3D,MAAM,OAAO,GAAwB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,SAAS,CAAC,IAAuB,EAAE,IAAY;IAC7D,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,qBAAqB,CAAC,IAAuB;IAC3D,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;IAC1B,OAAO,OAAO,EAAE,CAAC;QACf,IACE,OAAO,CAAC,IAAI,KAAK,sBAAsB;YACvC,OAAO,CAAC,IAAI,KAAK,gBAAgB;YACjC,OAAO,CAAC,IAAI,KAAK,qBAAqB;YACtC,OAAO,CAAC,IAAI,KAAK,mBAAmB,EACpC,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { ReactGraph } from '../graph/graph.js';
2
+ export interface IndexStats {
3
+ totalFiles: number;
4
+ parsedFiles: number;
5
+ skippedFiles: number;
6
+ nodes: number;
7
+ edges: number;
8
+ durationMs: number;
9
+ }
10
+ export declare function indexProject(projectDir: string, exclude?: string[], onProgress?: (file: string, current: number, total: number) => void): Promise<{
11
+ graph: ReactGraph;
12
+ stats: IndexStats;
13
+ }>;
14
+ //# sourceMappingURL=indexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../../src/parser/indexer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAM/C,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,MAAM,EAAO,EACtB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAClE,OAAO,CAAC;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC,CA6GnD"}
@@ -0,0 +1,167 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { createHash } from 'node:crypto';
3
+ import { join } from 'node:path';
4
+ import { ReactGraph } from '../graph/graph.js';
5
+ import { saveGraph, loadGraph } from '../graph/serialize.js';
6
+ import { walkProject } from './walker.js';
7
+ import { processFile } from './pipeline.js';
8
+ export async function indexProject(projectDir, exclude = [], onProgress) {
9
+ const start = Date.now();
10
+ const files = await walkProject(projectDir, exclude);
11
+ const oldHashes = await loadHashes(projectDir);
12
+ const existingGraph = await loadGraph(projectDir);
13
+ const newHashes = {};
14
+ // --- Pass 1: Extract all nodes + intra-file edges ---
15
+ // Accumulate globalNodes so later files can see stores/contexts from earlier ones
16
+ const globalNodes = [];
17
+ const graph = new ReactGraph();
18
+ let parsedFiles = 0;
19
+ let skippedFiles = 0;
20
+ const parsedFilePaths = []; // track which files we actually parsed
21
+ for (let i = 0; i < files.length; i++) {
22
+ const { absolutePath, relativePath } = files[i];
23
+ onProgress?.(relativePath, i + 1, files.length);
24
+ const content = await readFile(absolutePath, 'utf-8');
25
+ const hash = computeHash(content);
26
+ newHashes[relativePath] = hash;
27
+ // Reuse from cache if unchanged
28
+ if (oldHashes[relativePath] === hash && existingGraph) {
29
+ const existingNodes = existingGraph.getNodesByFile(relativePath);
30
+ for (const node of existingNodes) {
31
+ graph.addNode(node);
32
+ globalNodes.push(node);
33
+ }
34
+ const existingEdges = existingNodes.flatMap(n => [
35
+ ...existingGraph.getEdgesFrom(n.id),
36
+ ...existingGraph.getEdgesTo(n.id),
37
+ ]);
38
+ const seen = new Set();
39
+ for (const edge of existingEdges) {
40
+ const key = `${edge.source}|${edge.target}|${edge.kind}`;
41
+ if (!seen.has(key)) {
42
+ seen.add(key);
43
+ graph.addEdge(edge);
44
+ }
45
+ }
46
+ skippedFiles++;
47
+ continue;
48
+ }
49
+ try {
50
+ const result = await processFile(relativePath, projectDir, globalNodes);
51
+ for (const node of result.nodes) {
52
+ graph.addNode(node);
53
+ globalNodes.push(node);
54
+ }
55
+ for (const edge of result.edges)
56
+ graph.addEdge(edge);
57
+ parsedFiles++;
58
+ parsedFilePaths.push(relativePath);
59
+ }
60
+ catch (err) {
61
+ console.error(`Warning: failed to parse ${relativePath}: ${err}`);
62
+ parsedFiles++;
63
+ }
64
+ }
65
+ // --- Pass 2: Re-process early files that missed cross-file references ---
66
+ // Files processed before stores/contexts were discovered may lack edges.
67
+ // Re-run only files that were parsed in pass 1 AND processed before a
68
+ // store/context/hook was discovered in a later file.
69
+ const crossFileNodeKinds = new Set(['Store', 'Context', 'Hook', 'Component']);
70
+ const allCrossFileNodes = globalNodes.filter(n => crossFileNodeKinds.has(n.kind));
71
+ if (allCrossFileNodes.length > 0 && parsedFilePaths.length > 1) {
72
+ // Find files that were processed before cross-file targets existed
73
+ const crossFileNodeFiles = new Set(allCrossFileNodes.map(n => n.file));
74
+ for (const filePath of parsedFilePaths) {
75
+ // Skip files that define the cross-file nodes themselves
76
+ if (crossFileNodeFiles.has(filePath))
77
+ continue;
78
+ // Re-process with full global node visibility
79
+ try {
80
+ // Remove old edges from this file's nodes
81
+ graph.removeNodesByFile(filePath);
82
+ const result = await processFile(filePath, projectDir, globalNodes);
83
+ for (const node of result.nodes)
84
+ graph.addNode(node);
85
+ for (const edge of result.edges)
86
+ graph.addEdge(edge);
87
+ }
88
+ catch {
89
+ // Already processed in pass 1, skip errors
90
+ }
91
+ }
92
+ }
93
+ // Resolution pass: replace remaining unresolved targets
94
+ resolveUnresolvedEdges(graph);
95
+ await saveGraph(graph, projectDir);
96
+ await saveHashes(projectDir, newHashes);
97
+ const stats = {
98
+ totalFiles: files.length,
99
+ parsedFiles,
100
+ skippedFiles,
101
+ nodes: graph.stats().totalNodes,
102
+ edges: graph.stats().totalEdges,
103
+ durationMs: Date.now() - start,
104
+ };
105
+ return { graph, stats };
106
+ }
107
+ function computeHash(content) {
108
+ return createHash('sha256').update(content).digest('hex').slice(0, 16);
109
+ }
110
+ async function loadHashes(projectDir) {
111
+ try {
112
+ const raw = await readFile(join(projectDir, '.reactgraph', 'file-hashes.json'), 'utf-8');
113
+ return JSON.parse(raw);
114
+ }
115
+ catch {
116
+ return {};
117
+ }
118
+ }
119
+ async function saveHashes(projectDir, hashes) {
120
+ const dir = join(projectDir, '.reactgraph');
121
+ await mkdir(dir, { recursive: true });
122
+ await writeFile(join(dir, 'file-hashes.json'), JSON.stringify(hashes, null, 2));
123
+ }
124
+ /**
125
+ * Replace unresolved edge targets with actual node IDs.
126
+ */
127
+ function resolveUnresolvedEdges(graph) {
128
+ const allNodes = graph.getAllNodes();
129
+ const nameToId = new Map();
130
+ for (const node of allNodes) {
131
+ if (node.kind === 'Component' || node.kind === 'Hook' || node.kind === 'Store' || node.kind === 'Context') {
132
+ if (!nameToId.has(node.name)) {
133
+ nameToId.set(node.name, node.id);
134
+ }
135
+ }
136
+ }
137
+ const oldEdges = graph.getAllEdges();
138
+ const resolvedEdges = oldEdges.map(edge => {
139
+ let { source, target } = edge;
140
+ let changed = false;
141
+ if (source.startsWith('unresolved:')) {
142
+ const name = source.slice(11);
143
+ const resolved = nameToId.get(name);
144
+ if (resolved) {
145
+ source = resolved;
146
+ changed = true;
147
+ }
148
+ }
149
+ if (target.startsWith('unresolved:')) {
150
+ const name = target.slice(11);
151
+ const resolved = nameToId.get(name);
152
+ if (resolved) {
153
+ target = resolved;
154
+ changed = true;
155
+ }
156
+ }
157
+ return changed ? { ...edge, source, target } : edge;
158
+ });
159
+ if (resolvedEdges.some((e, i) => e !== oldEdges[i])) {
160
+ graph.clear();
161
+ for (const node of allNodes)
162
+ graph.addNode(node);
163
+ for (const edge of resolvedEdges)
164
+ graph.addEdge(edge);
165
+ }
166
+ }
167
+ //# sourceMappingURL=indexer.js.map