@saluzi/codegraph 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/dist/bin/codegraph.d.ts +25 -0
  2. package/dist/bin/node-version-check.d.ts +37 -0
  3. package/dist/bin/uninstall.d.ts +14 -0
  4. package/dist/context/formatter.d.ts +33 -0
  5. package/dist/context/formatter.js +244 -0
  6. package/dist/context/index.d.ts +117 -0
  7. package/dist/context/index.js +1050 -0
  8. package/dist/db/index.d.ts +101 -0
  9. package/dist/db/index.js +250 -0
  10. package/dist/db/migrations.d.ts +47 -0
  11. package/dist/db/migrations.js +131 -0
  12. package/dist/db/queries.d.ts +291 -0
  13. package/dist/db/queries.js +1349 -0
  14. package/dist/db/schema.sql +151 -0
  15. package/dist/db/sqlite-adapter.d.ts +49 -0
  16. package/dist/db/sqlite-adapter.js +141 -0
  17. package/dist/directory.d.ts +62 -0
  18. package/dist/directory.js +264 -0
  19. package/dist/errors.d.ts +149 -0
  20. package/dist/errors.js +219 -0
  21. package/dist/extraction/dfm-extractor.d.ts +31 -0
  22. package/dist/extraction/dfm-extractor.js +151 -0
  23. package/dist/extraction/grammars.d.ts +94 -0
  24. package/dist/extraction/grammars.js +357 -0
  25. package/dist/extraction/index.d.ts +148 -0
  26. package/dist/extraction/index.js +1286 -0
  27. package/dist/extraction/languages/c-cpp.d.ts +4 -0
  28. package/dist/extraction/languages/c-cpp.js +126 -0
  29. package/dist/extraction/languages/csharp.d.ts +3 -0
  30. package/dist/extraction/languages/csharp.js +72 -0
  31. package/dist/extraction/languages/dart.d.ts +3 -0
  32. package/dist/extraction/languages/dart.js +192 -0
  33. package/dist/extraction/languages/go.d.ts +3 -0
  34. package/dist/extraction/languages/go.js +58 -0
  35. package/dist/extraction/languages/index.d.ts +10 -0
  36. package/dist/extraction/languages/index.js +49 -0
  37. package/dist/extraction/languages/java.d.ts +3 -0
  38. package/dist/extraction/languages/java.js +64 -0
  39. package/dist/extraction/languages/javascript.d.ts +3 -0
  40. package/dist/extraction/languages/javascript.js +90 -0
  41. package/dist/extraction/languages/kotlin.d.ts +3 -0
  42. package/dist/extraction/languages/kotlin.js +253 -0
  43. package/dist/extraction/languages/lua.d.ts +3 -0
  44. package/dist/extraction/languages/lua.js +150 -0
  45. package/dist/extraction/languages/luau.d.ts +3 -0
  46. package/dist/extraction/languages/luau.js +37 -0
  47. package/dist/extraction/languages/pascal.d.ts +3 -0
  48. package/dist/extraction/languages/pascal.js +66 -0
  49. package/dist/extraction/languages/php.d.ts +3 -0
  50. package/dist/extraction/languages/php.js +107 -0
  51. package/dist/extraction/languages/python.d.ts +3 -0
  52. package/dist/extraction/languages/python.js +56 -0
  53. package/dist/extraction/languages/ruby.d.ts +3 -0
  54. package/dist/extraction/languages/ruby.js +114 -0
  55. package/dist/extraction/languages/rust.d.ts +3 -0
  56. package/dist/extraction/languages/rust.js +109 -0
  57. package/dist/extraction/languages/scala.d.ts +3 -0
  58. package/dist/extraction/languages/scala.js +139 -0
  59. package/dist/extraction/languages/swift.d.ts +3 -0
  60. package/dist/extraction/languages/swift.js +91 -0
  61. package/dist/extraction/languages/typescript.d.ts +3 -0
  62. package/dist/extraction/languages/typescript.js +129 -0
  63. package/dist/extraction/liquid-extractor.d.ts +52 -0
  64. package/dist/extraction/liquid-extractor.js +313 -0
  65. package/dist/extraction/parse-worker.d.ts +8 -0
  66. package/dist/extraction/parse-worker.js +94 -0
  67. package/dist/extraction/svelte-extractor.d.ts +56 -0
  68. package/dist/extraction/svelte-extractor.js +272 -0
  69. package/dist/extraction/tree-sitter-helpers.d.ts +39 -0
  70. package/dist/extraction/tree-sitter-helpers.js +103 -0
  71. package/dist/extraction/tree-sitter-types.d.ts +191 -0
  72. package/dist/extraction/tree-sitter-types.js +10 -0
  73. package/dist/extraction/tree-sitter.d.ts +238 -0
  74. package/dist/extraction/tree-sitter.js +2430 -0
  75. package/dist/extraction/vue-extractor.d.ts +36 -0
  76. package/dist/extraction/vue-extractor.js +163 -0
  77. package/dist/extraction/wasm/tree-sitter-c.wasm +0 -0
  78. package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  79. package/dist/extraction/wasm/tree-sitter-cpp.wasm +0 -0
  80. package/dist/extraction/wasm/tree-sitter-dart.wasm +0 -0
  81. package/dist/extraction/wasm/tree-sitter-go.wasm +0 -0
  82. package/dist/extraction/wasm/tree-sitter-java.wasm +0 -0
  83. package/dist/extraction/wasm/tree-sitter-javascript.wasm +0 -0
  84. package/dist/extraction/wasm/tree-sitter-kotlin.wasm +0 -0
  85. package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
  86. package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
  87. package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
  88. package/dist/extraction/wasm/tree-sitter-php.wasm +0 -0
  89. package/dist/extraction/wasm/tree-sitter-python.wasm +0 -0
  90. package/dist/extraction/wasm/tree-sitter-ruby.wasm +0 -0
  91. package/dist/extraction/wasm/tree-sitter-rust.wasm +0 -0
  92. package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  93. package/dist/extraction/wasm/tree-sitter-swift.wasm +0 -0
  94. package/dist/extraction/wasm/tree-sitter-tsx.wasm +0 -0
  95. package/dist/extraction/wasm/tree-sitter-typescript.wasm +0 -0
  96. package/dist/extraction/wasm-runtime-flags.d.ts +46 -0
  97. package/dist/extraction/wasm-runtime-flags.js +105 -0
  98. package/dist/graph/index.d.ts +8 -0
  99. package/dist/graph/index.js +13 -0
  100. package/dist/graph/queries.d.ts +109 -0
  101. package/dist/graph/queries.js +366 -0
  102. package/dist/graph/traversal.d.ts +137 -0
  103. package/dist/graph/traversal.js +528 -0
  104. package/dist/index.d.ts +509 -0
  105. package/dist/index.js +800 -0
  106. package/dist/installer/claude-md-template.d.ts +19 -0
  107. package/dist/installer/config-writer.d.ts +29 -0
  108. package/dist/installer/index.d.ts +140 -0
  109. package/dist/installer/instructions-template.d.ts +30 -0
  110. package/dist/installer/targets/claude.d.ts +55 -0
  111. package/dist/installer/targets/codex.d.ts +18 -0
  112. package/dist/installer/targets/cursor.d.ts +35 -0
  113. package/dist/installer/targets/hermes.d.ts +18 -0
  114. package/dist/installer/targets/opencode.d.ts +30 -0
  115. package/dist/installer/targets/registry.d.ts +38 -0
  116. package/dist/installer/targets/shared.d.ts +92 -0
  117. package/dist/installer/targets/toml.d.ts +64 -0
  118. package/dist/installer/targets/types.d.ts +122 -0
  119. package/dist/mcp/index.d.ts +98 -0
  120. package/dist/mcp/server-instructions.d.ts +20 -0
  121. package/dist/mcp/tools.d.ts +269 -0
  122. package/dist/mcp/transport.d.ts +117 -0
  123. package/dist/resolution/frameworks/cargo-workspace.d.ts +20 -0
  124. package/dist/resolution/frameworks/cargo-workspace.js +225 -0
  125. package/dist/resolution/frameworks/csharp.d.ts +8 -0
  126. package/dist/resolution/frameworks/csharp.js +213 -0
  127. package/dist/resolution/frameworks/drupal.d.ts +51 -0
  128. package/dist/resolution/frameworks/drupal.js +335 -0
  129. package/dist/resolution/frameworks/express.d.ts +8 -0
  130. package/dist/resolution/frameworks/express.js +225 -0
  131. package/dist/resolution/frameworks/go.d.ts +8 -0
  132. package/dist/resolution/frameworks/go.js +158 -0
  133. package/dist/resolution/frameworks/index.d.ts +52 -0
  134. package/dist/resolution/frameworks/index.js +137 -0
  135. package/dist/resolution/frameworks/java.d.ts +8 -0
  136. package/dist/resolution/frameworks/java.js +177 -0
  137. package/dist/resolution/frameworks/laravel.d.ts +13 -0
  138. package/dist/resolution/frameworks/laravel.js +248 -0
  139. package/dist/resolution/frameworks/nestjs.d.ts +26 -0
  140. package/dist/resolution/frameworks/nestjs.js +374 -0
  141. package/dist/resolution/frameworks/python.d.ts +10 -0
  142. package/dist/resolution/frameworks/python.js +278 -0
  143. package/dist/resolution/frameworks/react.d.ts +8 -0
  144. package/dist/resolution/frameworks/react.js +272 -0
  145. package/dist/resolution/frameworks/ruby.d.ts +8 -0
  146. package/dist/resolution/frameworks/ruby.js +198 -0
  147. package/dist/resolution/frameworks/rust.d.ts +8 -0
  148. package/dist/resolution/frameworks/rust.js +207 -0
  149. package/dist/resolution/frameworks/svelte.d.ts +9 -0
  150. package/dist/resolution/frameworks/svelte.js +249 -0
  151. package/dist/resolution/frameworks/swift.d.ts +10 -0
  152. package/dist/resolution/frameworks/swift.js +376 -0
  153. package/dist/resolution/frameworks/vue.d.ts +9 -0
  154. package/dist/resolution/frameworks/vue.js +306 -0
  155. package/dist/resolution/import-resolver.d.ts +61 -0
  156. package/dist/resolution/import-resolver.js +663 -0
  157. package/dist/resolution/index.d.ts +118 -0
  158. package/dist/resolution/index.js +744 -0
  159. package/dist/resolution/lru-cache.d.ts +24 -0
  160. package/dist/resolution/lru-cache.js +62 -0
  161. package/dist/resolution/name-matcher.d.ts +50 -0
  162. package/dist/resolution/name-matcher.js +384 -0
  163. package/dist/resolution/path-aliases.d.ts +72 -0
  164. package/dist/resolution/path-aliases.js +238 -0
  165. package/dist/resolution/strip-comments.d.ts +40 -0
  166. package/dist/resolution/strip-comments.js +441 -0
  167. package/dist/resolution/types.d.ts +181 -0
  168. package/dist/resolution/types.js +8 -0
  169. package/dist/search/query-parser.d.ts +61 -0
  170. package/dist/search/query-parser.js +177 -0
  171. package/dist/search/query-utils.d.ts +59 -0
  172. package/dist/search/query-utils.js +383 -0
  173. package/dist/sync/git-hooks.d.ts +54 -0
  174. package/dist/sync/git-hooks.js +223 -0
  175. package/dist/sync/index.d.ts +25 -0
  176. package/dist/sync/index.js +28 -0
  177. package/dist/sync/watch-policy.d.ts +51 -0
  178. package/dist/sync/watch-policy.js +124 -0
  179. package/dist/sync/watcher.d.ts +83 -0
  180. package/dist/sync/watcher.js +192 -0
  181. package/dist/types.d.ts +433 -0
  182. package/dist/types.js +75 -0
  183. package/dist/ui/glyphs.d.ts +42 -0
  184. package/dist/ui/shimmer-progress.d.ts +11 -0
  185. package/dist/ui/shimmer-worker.d.ts +2 -0
  186. package/dist/ui/types.d.ts +20 -0
  187. package/dist/utils.d.ts +231 -0
  188. package/dist/utils.js +549 -0
  189. package/package.json +24 -0
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ /**
3
+ * Python Framework Resolver
4
+ *
5
+ * Handles Django, Flask, and FastAPI patterns.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.fastapiResolver = exports.flaskResolver = exports.djangoResolver = void 0;
9
+ const strip_comments_1 = require("../strip-comments");
10
+ exports.djangoResolver = {
11
+ name: 'django',
12
+ languages: ['python'],
13
+ detect(context) {
14
+ const requirements = context.readFile('requirements.txt');
15
+ if (requirements && requirements.toLowerCase().includes('django'))
16
+ return true;
17
+ const setup = context.readFile('setup.py');
18
+ if (setup && setup.toLowerCase().includes('django'))
19
+ return true;
20
+ const pyproject = context.readFile('pyproject.toml');
21
+ if (pyproject && pyproject.toLowerCase().includes('django'))
22
+ return true;
23
+ return context.fileExists('manage.py');
24
+ },
25
+ resolve(ref, context) {
26
+ if (ref.referenceName.endsWith('Model') || /^[A-Z][a-z]+$/.test(ref.referenceName)) {
27
+ const result = resolveByNameAndKind(ref.referenceName, CLASS_KINDS, MODEL_DIRS, context);
28
+ if (result)
29
+ return { original: ref, targetNodeId: result, confidence: 0.8, resolvedBy: 'framework' };
30
+ }
31
+ if (ref.referenceName.endsWith('View') || ref.referenceName.endsWith('ViewSet')) {
32
+ const result = resolveByNameAndKind(ref.referenceName, VIEW_KINDS, VIEW_DIRS, context);
33
+ if (result)
34
+ return { original: ref, targetNodeId: result, confidence: 0.8, resolvedBy: 'framework' };
35
+ }
36
+ if (ref.referenceName.endsWith('Form')) {
37
+ const result = resolveByNameAndKind(ref.referenceName, CLASS_KINDS, FORM_DIRS, context);
38
+ if (result)
39
+ return { original: ref, targetNodeId: result, confidence: 0.8, resolvedBy: 'framework' };
40
+ }
41
+ return null;
42
+ },
43
+ extract(filePath, content) {
44
+ if (!filePath.endsWith('.py'))
45
+ return { nodes: [], references: [] };
46
+ const nodes = [];
47
+ const references = [];
48
+ const now = Date.now();
49
+ const safe = (0, strip_comments_1.stripCommentsForRegex)(content, 'python');
50
+ // path('url', handler, name=...) / re_path(r'...', handler) / url(r'...', handler)
51
+ // Capture groups: 1=function name, 2=url string, 3=handler expr
52
+ // Handler expr may contain one balanced () pair (e.g. View.as_view(), include('x.y'))
53
+ const routeRegex = /\b(path|re_path|url)\s*\(\s*r?['"]([^'"]+)['"]\s*,\s*([\w.]+(?:\s*\([^)]*\))?)/g;
54
+ let match;
55
+ while ((match = routeRegex.exec(safe)) !== null) {
56
+ const [, _fn, urlPath, handlerExpr] = match;
57
+ const line = safe.slice(0, match.index).split('\n').length;
58
+ const routeNode = {
59
+ id: `route:${filePath}:${line}:${urlPath}`,
60
+ kind: 'route',
61
+ name: urlPath,
62
+ qualifiedName: `${filePath}::route:${urlPath}`,
63
+ filePath,
64
+ startLine: line,
65
+ endLine: line,
66
+ startColumn: 0,
67
+ endColumn: match[0].length,
68
+ language: 'python',
69
+ updatedAt: now,
70
+ };
71
+ nodes.push(routeNode);
72
+ const handler = handlerExpr.trim();
73
+ const target = resolveHandlerName(handler);
74
+ if (target) {
75
+ references.push({
76
+ fromNodeId: routeNode.id,
77
+ referenceName: target.name,
78
+ referenceKind: target.kind,
79
+ line,
80
+ column: 0,
81
+ filePath,
82
+ language: 'python',
83
+ });
84
+ }
85
+ }
86
+ return { nodes, references };
87
+ },
88
+ };
89
+ /**
90
+ * Parse a Django URL handler expression and return the symbol/module to link.
91
+ * Returns null for shapes we can't confidently link (e.g. lambdas).
92
+ */
93
+ function resolveHandlerName(expr) {
94
+ // include('module.path')
95
+ const includeMatch = expr.match(/^include\s*\(\s*['"]([^'"]+)['"]/);
96
+ if (includeMatch)
97
+ return { name: includeMatch[1], kind: 'imports' };
98
+ // Strip trailing .as_view(...) or .as_view()
99
+ let head = expr.replace(/\.as_view\s*\([^)]*\)\s*$/, '');
100
+ // Drop any other trailing method call
101
+ head = head.replace(/\.\w+\s*\([^)]*\)\s*$/, '');
102
+ const dotted = head.split('.').filter(Boolean);
103
+ if (dotted.length === 0)
104
+ return null;
105
+ const last = dotted[dotted.length - 1];
106
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(last))
107
+ return null;
108
+ return { name: last, kind: 'references' };
109
+ }
110
+ exports.flaskResolver = {
111
+ name: 'flask',
112
+ languages: ['python'],
113
+ detect(context) {
114
+ const requirements = context.readFile('requirements.txt');
115
+ if (requirements && /\bflask\b/i.test(requirements))
116
+ return true;
117
+ const pyproject = context.readFile('pyproject.toml');
118
+ if (pyproject && /\bflask\b/i.test(pyproject))
119
+ return true;
120
+ for (const file of ['app.py', 'application.py', 'main.py', '__init__.py']) {
121
+ const content = context.readFile(file);
122
+ if (content && content.includes('Flask(__name__)'))
123
+ return true;
124
+ }
125
+ return false;
126
+ },
127
+ resolve(ref, context) {
128
+ if (ref.referenceName.endsWith('_bp') || ref.referenceName.endsWith('_blueprint')) {
129
+ const result = resolveByNameAndKind(ref.referenceName, VARIABLE_KINDS, [], context);
130
+ if (result)
131
+ return { original: ref, targetNodeId: result, confidence: 0.8, resolvedBy: 'framework' };
132
+ }
133
+ return null;
134
+ },
135
+ extract(filePath, content) {
136
+ if (!filePath.endsWith('.py'))
137
+ return { nodes: [], references: [] };
138
+ return extractDecoratorRoutes(filePath, (0, strip_comments_1.stripCommentsForRegex)(content, 'python'), {
139
+ // Flask: @x.route('/path', methods=[...])
140
+ decoratorRegex: /@(\w+)\.route\s*\(\s*['"]([^'"]+)['"](?:\s*,\s*methods\s*=\s*\[([^\]]+)\])?\s*\)\s*\n\s*(?:async\s+)?def\s+(\w+)/g,
141
+ defaultMethod: 'GET',
142
+ methodFromGroup: 3,
143
+ pathGroup: 2,
144
+ handlerGroup: 4,
145
+ language: 'python',
146
+ });
147
+ },
148
+ };
149
+ exports.fastapiResolver = {
150
+ name: 'fastapi',
151
+ languages: ['python'],
152
+ detect(context) {
153
+ const requirements = context.readFile('requirements.txt');
154
+ if (requirements && /\bfastapi\b/i.test(requirements))
155
+ return true;
156
+ const pyproject = context.readFile('pyproject.toml');
157
+ if (pyproject && /\bfastapi\b/i.test(pyproject))
158
+ return true;
159
+ for (const file of ['app.py', 'main.py', 'api.py']) {
160
+ const content = context.readFile(file);
161
+ if (content && content.includes('FastAPI('))
162
+ return true;
163
+ }
164
+ return false;
165
+ },
166
+ resolve(ref, context) {
167
+ if (ref.referenceName.endsWith('_router') || ref.referenceName === 'router') {
168
+ const result = resolveByNameAndKind(ref.referenceName, VARIABLE_KINDS, ROUTER_DIRS, context);
169
+ if (result)
170
+ return { original: ref, targetNodeId: result, confidence: 0.8, resolvedBy: 'framework' };
171
+ }
172
+ if (ref.referenceName.startsWith('get_') || ref.referenceName.startsWith('Depends')) {
173
+ const result = resolveByNameAndKind(ref.referenceName, FUNCTION_KINDS, DEP_DIRS, context);
174
+ if (result)
175
+ return { original: ref, targetNodeId: result, confidence: 0.75, resolvedBy: 'framework' };
176
+ }
177
+ return null;
178
+ },
179
+ extract(filePath, content) {
180
+ if (!filePath.endsWith('.py'))
181
+ return { nodes: [], references: [] };
182
+ return extractDecoratorRoutes(filePath, (0, strip_comments_1.stripCommentsForRegex)(content, 'python'), {
183
+ // FastAPI: @x.METHOD('/path') -> handler on the next def line
184
+ decoratorRegex: /@(\w+)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"]([^'"]+)['"]/g,
185
+ defaultMethod: '',
186
+ methodGroup: 2,
187
+ pathGroup: 3,
188
+ findHandler: true,
189
+ language: 'python',
190
+ });
191
+ },
192
+ };
193
+ function extractDecoratorRoutes(filePath, content, opts) {
194
+ const nodes = [];
195
+ const references = [];
196
+ const now = Date.now();
197
+ let match;
198
+ while ((match = opts.decoratorRegex.exec(content)) !== null) {
199
+ const routePath = match[opts.pathGroup];
200
+ let method = opts.defaultMethod;
201
+ if (opts.methodGroup && match[opts.methodGroup]) {
202
+ method = match[opts.methodGroup].toUpperCase();
203
+ }
204
+ else if (opts.methodFromGroup && match[opts.methodFromGroup]) {
205
+ const m = match[opts.methodFromGroup].match(/['"]([A-Z]+)['"]/i);
206
+ if (m)
207
+ method = m[1].toUpperCase();
208
+ }
209
+ const line = content.slice(0, match.index).split('\n').length;
210
+ const name = method ? `${method} ${routePath}` : routePath;
211
+ const routeNode = {
212
+ id: `route:${filePath}:${line}:${method}:${routePath}`,
213
+ kind: 'route',
214
+ name,
215
+ qualifiedName: `${filePath}::${method}:${routePath}`,
216
+ filePath,
217
+ startLine: line,
218
+ endLine: line,
219
+ startColumn: 0,
220
+ endColumn: match[0].length,
221
+ language: opts.language,
222
+ updatedAt: now,
223
+ };
224
+ nodes.push(routeNode);
225
+ let handlerName;
226
+ if (opts.handlerGroup && match[opts.handlerGroup]) {
227
+ handlerName = match[opts.handlerGroup];
228
+ }
229
+ else if (opts.findHandler) {
230
+ const tail = content.slice(match.index + match[0].length);
231
+ const defMatch = tail.match(/\n\s*(?:async\s+)?def\s+(\w+)/);
232
+ if (defMatch)
233
+ handlerName = defMatch[1];
234
+ }
235
+ if (handlerName) {
236
+ references.push({
237
+ fromNodeId: routeNode.id,
238
+ referenceName: handlerName,
239
+ referenceKind: 'references',
240
+ line,
241
+ column: 0,
242
+ filePath,
243
+ language: 'python',
244
+ });
245
+ }
246
+ }
247
+ return { nodes, references };
248
+ }
249
+ // Directory patterns
250
+ const MODEL_DIRS = ['models', 'app/models', 'src/models'];
251
+ const VIEW_DIRS = ['views', 'app/views', 'src/views', 'api/views'];
252
+ const FORM_DIRS = ['forms', 'app/forms', 'src/forms'];
253
+ const ROUTER_DIRS = ['/routers/', '/api/', '/routes/', '/endpoints/'];
254
+ const DEP_DIRS = ['/dependencies/', '/deps/', '/core/'];
255
+ const CLASS_KINDS = new Set(['class']);
256
+ const VIEW_KINDS = new Set(['class', 'function']);
257
+ const VARIABLE_KINDS = new Set(['variable']);
258
+ const FUNCTION_KINDS = new Set(['function']);
259
+ /**
260
+ * Resolve a symbol by name using indexed queries instead of scanning all files.
261
+ */
262
+ function resolveByNameAndKind(name, kinds, preferredDirPatterns, context) {
263
+ const candidates = context.getNodesByName(name);
264
+ if (candidates.length === 0)
265
+ return null;
266
+ const kindFiltered = candidates.filter((n) => kinds.has(n.kind));
267
+ if (kindFiltered.length === 0)
268
+ return null;
269
+ // Prefer candidates in framework-conventional directories
270
+ if (preferredDirPatterns.length > 0) {
271
+ const preferred = kindFiltered.filter((n) => preferredDirPatterns.some((d) => n.filePath.includes(d)));
272
+ if (preferred.length > 0)
273
+ return preferred[0].id;
274
+ }
275
+ // Fall back to any match
276
+ return kindFiltered[0].id;
277
+ }
278
+ //# sourceMappingURL=python.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * React Framework Resolver
3
+ *
4
+ * Handles React and Next.js patterns.
5
+ */
6
+ import { FrameworkResolver } from '../types'
7
+ export declare const reactResolver: FrameworkResolver
8
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1,272 @@
1
+ "use strict";
2
+ /**
3
+ * React Framework Resolver
4
+ *
5
+ * Handles React and Next.js patterns.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.reactResolver = void 0;
9
+ exports.reactResolver = {
10
+ name: 'react',
11
+ languages: ['javascript', 'typescript'],
12
+ detect(context) {
13
+ // Check for React in package.json
14
+ const packageJson = context.readFile('package.json');
15
+ if (packageJson) {
16
+ try {
17
+ const pkg = JSON.parse(packageJson);
18
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
19
+ if (deps.react || deps.next || deps['react-native']) {
20
+ return true;
21
+ }
22
+ }
23
+ catch {
24
+ // Invalid JSON
25
+ }
26
+ }
27
+ // Check for .jsx/.tsx files
28
+ const allFiles = context.getAllFiles();
29
+ return allFiles.some((f) => f.endsWith('.jsx') || f.endsWith('.tsx'));
30
+ },
31
+ resolve(ref, context) {
32
+ // Pattern 1: Component references (PascalCase)
33
+ if (isPascalCase(ref.referenceName) && !isBuiltInType(ref.referenceName)) {
34
+ const result = resolveComponent(ref.referenceName, ref.filePath, context);
35
+ if (result) {
36
+ return {
37
+ original: ref,
38
+ targetNodeId: result,
39
+ confidence: 0.8,
40
+ resolvedBy: 'framework',
41
+ };
42
+ }
43
+ }
44
+ // Pattern 2: Hook references (use*)
45
+ if (ref.referenceName.startsWith('use') && ref.referenceName.length > 3) {
46
+ const result = resolveHook(ref.referenceName, context);
47
+ if (result) {
48
+ return {
49
+ original: ref,
50
+ targetNodeId: result,
51
+ confidence: 0.85,
52
+ resolvedBy: 'framework',
53
+ };
54
+ }
55
+ }
56
+ // Pattern 3: Context references
57
+ if (ref.referenceName.endsWith('Context') || ref.referenceName.endsWith('Provider')) {
58
+ const result = resolveContext(ref.referenceName, context);
59
+ if (result) {
60
+ return {
61
+ original: ref,
62
+ targetNodeId: result,
63
+ confidence: 0.8,
64
+ resolvedBy: 'framework',
65
+ };
66
+ }
67
+ }
68
+ return null;
69
+ },
70
+ extract(filePath, content) {
71
+ const nodes = [];
72
+ const now = Date.now();
73
+ // Extract component definitions
74
+ // function Component() or const Component = () =>
75
+ const componentPatterns = [
76
+ // Function components
77
+ /(?:export\s+)?function\s+([A-Z][a-zA-Z0-9]*)\s*\(/g,
78
+ // Arrow function components
79
+ /(?:export\s+)?(?:const|let)\s+([A-Z][a-zA-Z0-9]*)\s*=\s*(?:\([^)]*\)|[a-zA-Z_][a-zA-Z0-9_]*)\s*=>/g,
80
+ // forwardRef components
81
+ /(?:export\s+)?(?:const|let)\s+([A-Z][a-zA-Z0-9]*)\s*=\s*(?:React\.)?forwardRef/g,
82
+ // memo components
83
+ /(?:export\s+)?(?:const|let)\s+([A-Z][a-zA-Z0-9]*)\s*=\s*(?:React\.)?memo/g,
84
+ ];
85
+ for (const pattern of componentPatterns) {
86
+ let match;
87
+ while ((match = pattern.exec(content)) !== null) {
88
+ const [fullMatch, name] = match;
89
+ const line = content.slice(0, match.index).split('\n').length;
90
+ // Check if it returns JSX (rough heuristic)
91
+ const afterMatch = content.slice(match.index + fullMatch.length, match.index + fullMatch.length + 500);
92
+ const hasJSX = afterMatch.includes('<') && (afterMatch.includes('/>') || afterMatch.includes('</'));
93
+ if (hasJSX) {
94
+ nodes.push({
95
+ id: `component:${filePath}:${name}:${line}`,
96
+ kind: 'component',
97
+ name: name,
98
+ qualifiedName: `${filePath}::${name}`,
99
+ filePath,
100
+ startLine: line,
101
+ endLine: line,
102
+ startColumn: 0,
103
+ endColumn: fullMatch.length,
104
+ language: filePath.endsWith('.tsx') ? 'tsx' : 'jsx',
105
+ isExported: fullMatch.includes('export'),
106
+ updatedAt: now,
107
+ });
108
+ }
109
+ }
110
+ }
111
+ // Extract custom hooks
112
+ const hookPattern = /(?:export\s+)?(?:function|const|let)\s+(use[A-Z][a-zA-Z0-9]*)\s*[=(]/g;
113
+ let hookMatch;
114
+ while ((hookMatch = hookPattern.exec(content)) !== null) {
115
+ const [fullMatch, name] = hookMatch;
116
+ const line = content.slice(0, hookMatch.index).split('\n').length;
117
+ nodes.push({
118
+ id: `hook:${filePath}:${name}:${line}`,
119
+ kind: 'function',
120
+ name: name,
121
+ qualifiedName: `${filePath}::${name}`,
122
+ filePath,
123
+ startLine: line,
124
+ endLine: line,
125
+ startColumn: 0,
126
+ endColumn: fullMatch.length,
127
+ language: filePath.endsWith('.ts') || filePath.endsWith('.tsx') ? 'typescript' : 'javascript',
128
+ isExported: fullMatch.includes('export'),
129
+ updatedAt: now,
130
+ });
131
+ }
132
+ // Extract Next.js pages/routes (pages directory convention)
133
+ if (filePath.includes('pages/') || filePath.includes('app/')) {
134
+ // Default export in pages becomes a route
135
+ if (content.includes('export default')) {
136
+ const routePath = filePathToRoute(filePath);
137
+ if (routePath) {
138
+ const line = content.indexOf('export default');
139
+ const lineNum = content.slice(0, line).split('\n').length;
140
+ nodes.push({
141
+ id: `route:${filePath}:${routePath}:${lineNum}`,
142
+ kind: 'route',
143
+ name: routePath,
144
+ qualifiedName: `${filePath}::route:${routePath}`,
145
+ filePath,
146
+ startLine: lineNum,
147
+ endLine: lineNum,
148
+ startColumn: 0,
149
+ endColumn: 0,
150
+ language: filePath.endsWith('.tsx') ? 'tsx' : filePath.endsWith('.ts') ? 'typescript' : 'javascript',
151
+ updatedAt: now,
152
+ });
153
+ }
154
+ }
155
+ }
156
+ return { nodes, references: [] };
157
+ },
158
+ };
159
+ /**
160
+ * Check if string is PascalCase
161
+ */
162
+ function isPascalCase(str) {
163
+ return /^[A-Z][a-zA-Z0-9]*$/.test(str);
164
+ }
165
+ /**
166
+ * Check if name is a built-in type
167
+ */
168
+ function isBuiltInType(name) {
169
+ return BUILT_IN_TYPES.has(name);
170
+ }
171
+ const BUILT_IN_TYPES = new Set([
172
+ 'Array', 'Boolean', 'Date', 'Error', 'Function', 'JSON', 'Math', 'Number',
173
+ 'Object', 'Promise', 'RegExp', 'String', 'Symbol', 'Map', 'Set', 'WeakMap', 'WeakSet',
174
+ 'React', 'Component', 'Fragment', 'Suspense', 'StrictMode',
175
+ ]);
176
+ const COMPONENT_KINDS = new Set(['component', 'function', 'class']);
177
+ /**
178
+ * Resolve a component reference using name-based lookup
179
+ */
180
+ function resolveComponent(name, fromFile, context) {
181
+ const candidates = context.getNodesByName(name);
182
+ if (candidates.length === 0)
183
+ return null;
184
+ const components = candidates.filter((n) => COMPONENT_KINDS.has(n.kind));
185
+ if (components.length === 0)
186
+ return null;
187
+ // Prefer same directory
188
+ const fromDir = fromFile.substring(0, fromFile.lastIndexOf('/'));
189
+ const sameDir = components.filter((n) => n.filePath.startsWith(fromDir));
190
+ if (sameDir.length > 0)
191
+ return sameDir[0].id;
192
+ // Prefer component directories
193
+ const COMPONENT_DIRS = ['/components/', '/src/components/', '/app/components/', '/pages/', '/src/pages/', '/views/', '/src/views/'];
194
+ const preferred = components.filter((n) => COMPONENT_DIRS.some((d) => n.filePath.includes(d)));
195
+ if (preferred.length > 0)
196
+ return preferred[0].id;
197
+ return components[0].id;
198
+ }
199
+ /**
200
+ * Resolve a custom hook reference using name-based lookup
201
+ */
202
+ function resolveHook(name, context) {
203
+ const candidates = context.getNodesByName(name);
204
+ if (candidates.length === 0)
205
+ return null;
206
+ const hooks = candidates.filter((n) => n.kind === 'function' && n.name.startsWith('use'));
207
+ if (hooks.length === 0)
208
+ return null;
209
+ // Prefer hooks directories
210
+ const HOOK_DIRS = ['/hooks/', '/src/hooks/', '/lib/hooks/', '/utils/hooks/'];
211
+ const preferred = hooks.filter((n) => HOOK_DIRS.some((d) => n.filePath.includes(d)));
212
+ if (preferred.length > 0)
213
+ return preferred[0].id;
214
+ return hooks[0].id;
215
+ }
216
+ /**
217
+ * Resolve a context reference using name-based lookup
218
+ */
219
+ function resolveContext(name, context) {
220
+ const candidates = context.getNodesByName(name);
221
+ if (candidates.length === 0) {
222
+ // Try without Context/Provider suffix
223
+ const baseName = name.replace(/Context$|Provider$/, '');
224
+ if (baseName !== name) {
225
+ const baseCandidates = context.getNodesByName(baseName);
226
+ if (baseCandidates.length > 0)
227
+ return baseCandidates[0].id;
228
+ }
229
+ return null;
230
+ }
231
+ // Prefer context directories
232
+ const CONTEXT_DIRS = ['/context/', '/contexts/', '/src/context/', '/src/contexts/', '/providers/', '/src/providers/'];
233
+ const preferred = candidates.filter((n) => CONTEXT_DIRS.some((d) => n.filePath.includes(d)));
234
+ if (preferred.length > 0)
235
+ return preferred[0].id;
236
+ return candidates[0].id;
237
+ }
238
+ /**
239
+ * Convert file path to Next.js route
240
+ */
241
+ function filePathToRoute(filePath) {
242
+ // pages/index.tsx -> /
243
+ // pages/about.tsx -> /about
244
+ // pages/blog/[slug].tsx -> /blog/:slug
245
+ // app/page.tsx -> /
246
+ // app/about/page.tsx -> /about
247
+ if (filePath.includes('pages/')) {
248
+ let route = filePath
249
+ .replace(/^.*pages\//, '/')
250
+ .replace(/\/index\.(tsx?|jsx?)$/, '')
251
+ .replace(/\.(tsx?|jsx?)$/, '')
252
+ .replace(/\[([^\]]+)\]/g, ':$1');
253
+ if (route === '')
254
+ route = '/';
255
+ return route;
256
+ }
257
+ if (filePath.includes('app/')) {
258
+ // App router - only page.tsx files are routes
259
+ if (!filePath.includes('page.')) {
260
+ return null;
261
+ }
262
+ let route = filePath
263
+ .replace(/^.*app\//, '/')
264
+ .replace(/\/page\.(tsx?|jsx?)$/, '')
265
+ .replace(/\[([^\]]+)\]/g, ':$1');
266
+ if (route === '')
267
+ route = '/';
268
+ return route;
269
+ }
270
+ return null;
271
+ }
272
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Ruby Framework Resolver
3
+ *
4
+ * Handles Ruby on Rails patterns.
5
+ */
6
+ import { FrameworkResolver } from '../types'
7
+ export declare const railsResolver: FrameworkResolver
8
+ //# sourceMappingURL=ruby.d.ts.map