@saluzi/codegraph 0.1.0 → 0.2.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.
- package/LICENSE +21 -0
- package/README.md +885 -0
- package/package.json +42 -10
- package/scripts/add-lang/bench.sh +60 -0
- package/scripts/add-lang/check-grammar.mjs +75 -0
- package/scripts/add-lang/dump-ast.mjs +103 -0
- package/scripts/add-lang/verify-extraction.mjs +70 -0
- package/scripts/agent-eval/ab-adoption.sh +91 -0
- package/scripts/agent-eval/ab-hook.sh +86 -0
- package/scripts/agent-eval/ab-impl.sh +78 -0
- package/scripts/agent-eval/ab-new-vs-baseline.sh +102 -0
- package/scripts/agent-eval/ab-sufficiency.sh +78 -0
- package/scripts/agent-eval/arms-F.sh +21 -0
- package/scripts/agent-eval/arms-matrix.sh +37 -0
- package/scripts/agent-eval/audit.sh +68 -0
- package/scripts/agent-eval/bench-readme.sh +28 -0
- package/scripts/agent-eval/bench-why-repo.sh +22 -0
- package/scripts/agent-eval/block-read-hook.sh +19 -0
- package/scripts/agent-eval/hook-settings.json +15 -0
- package/scripts/agent-eval/itrun.sh +120 -0
- package/scripts/agent-eval/offload-eval-3arm.sh +72 -0
- package/scripts/agent-eval/offload-eval-cost.mjs +133 -0
- package/scripts/agent-eval/offload-eval-effort.mjs +108 -0
- package/scripts/agent-eval/offload-eval-frontload-matrix.sh +25 -0
- package/scripts/agent-eval/offload-eval-frontload.sh +47 -0
- package/scripts/agent-eval/offload-eval-ground-truth.json +18 -0
- package/scripts/agent-eval/offload-eval-hook.mjs +84 -0
- package/scripts/agent-eval/offload-eval-judge.mjs +103 -0
- package/scripts/agent-eval/offload-eval-matrix.sh +20 -0
- package/scripts/agent-eval/offload-eval-metrics.mjs +94 -0
- package/scripts/agent-eval/offload-eval-refs1.sh +50 -0
- package/scripts/agent-eval/offload-eval-setup.sh +24 -0
- package/scripts/agent-eval/offload-eval-styles.sh +72 -0
- package/scripts/agent-eval/offload-eval-summarize.mjs +68 -0
- package/scripts/agent-eval/offload-eval.md +76 -0
- package/scripts/agent-eval/parse-arms.mjs +116 -0
- package/scripts/agent-eval/parse-bench-readme.mjs +84 -0
- package/scripts/agent-eval/parse-run.mjs +45 -0
- package/scripts/agent-eval/parse-session.mjs +93 -0
- package/scripts/agent-eval/probe-context.mjs +21 -0
- package/scripts/agent-eval/probe-explore.mjs +40 -0
- package/scripts/agent-eval/probe-node.mjs +20 -0
- package/scripts/agent-eval/probe-sweep.mjs +119 -0
- package/scripts/agent-eval/probe-trace.mjs +20 -0
- package/scripts/agent-eval/redirect-read-hook.sh +38 -0
- package/scripts/agent-eval/repro-concurrent-explore.mjs +119 -0
- package/scripts/agent-eval/repro-daemon-clients.mjs +125 -0
- package/scripts/agent-eval/run-agent.sh +34 -0
- package/scripts/agent-eval/run-all.sh +75 -0
- package/scripts/agent-eval/run-arms.sh +56 -0
- package/scripts/agent-eval/seq-matrix.mjs +137 -0
- package/scripts/build-bundle.sh +123 -0
- package/scripts/extract-release-notes.mjs +130 -0
- package/scripts/local-install.sh +41 -0
- package/scripts/npm-sdk.js +75 -0
- package/scripts/npm-shim.js +275 -0
- package/scripts/pack-npm.sh +119 -0
- package/scripts/prepare-release.mjs +270 -0
- package/dist/bin/codegraph.d.ts +0 -25
- package/dist/bin/node-version-check.d.ts +0 -37
- package/dist/bin/uninstall.d.ts +0 -14
- package/dist/context/formatter.d.ts +0 -33
- package/dist/context/formatter.js +0 -244
- package/dist/context/index.d.ts +0 -117
- package/dist/context/index.js +0 -1050
- package/dist/db/index.d.ts +0 -101
- package/dist/db/index.js +0 -250
- package/dist/db/migrations.d.ts +0 -47
- package/dist/db/migrations.js +0 -131
- package/dist/db/queries.d.ts +0 -291
- package/dist/db/queries.js +0 -1349
- package/dist/db/schema.sql +0 -151
- package/dist/db/sqlite-adapter.d.ts +0 -49
- package/dist/db/sqlite-adapter.js +0 -141
- package/dist/directory.d.ts +0 -62
- package/dist/directory.js +0 -264
- package/dist/errors.d.ts +0 -149
- package/dist/errors.js +0 -219
- package/dist/extraction/dfm-extractor.d.ts +0 -31
- package/dist/extraction/dfm-extractor.js +0 -151
- package/dist/extraction/grammars.d.ts +0 -94
- package/dist/extraction/grammars.js +0 -357
- package/dist/extraction/index.d.ts +0 -148
- package/dist/extraction/index.js +0 -1286
- package/dist/extraction/languages/c-cpp.d.ts +0 -4
- package/dist/extraction/languages/c-cpp.js +0 -126
- package/dist/extraction/languages/csharp.d.ts +0 -3
- package/dist/extraction/languages/csharp.js +0 -72
- package/dist/extraction/languages/dart.d.ts +0 -3
- package/dist/extraction/languages/dart.js +0 -192
- package/dist/extraction/languages/go.d.ts +0 -3
- package/dist/extraction/languages/go.js +0 -58
- package/dist/extraction/languages/index.d.ts +0 -10
- package/dist/extraction/languages/index.js +0 -49
- package/dist/extraction/languages/java.d.ts +0 -3
- package/dist/extraction/languages/java.js +0 -64
- package/dist/extraction/languages/javascript.d.ts +0 -3
- package/dist/extraction/languages/javascript.js +0 -90
- package/dist/extraction/languages/kotlin.d.ts +0 -3
- package/dist/extraction/languages/kotlin.js +0 -253
- package/dist/extraction/languages/lua.d.ts +0 -3
- package/dist/extraction/languages/lua.js +0 -150
- package/dist/extraction/languages/luau.d.ts +0 -3
- package/dist/extraction/languages/luau.js +0 -37
- package/dist/extraction/languages/pascal.d.ts +0 -3
- package/dist/extraction/languages/pascal.js +0 -66
- package/dist/extraction/languages/php.d.ts +0 -3
- package/dist/extraction/languages/php.js +0 -107
- package/dist/extraction/languages/python.d.ts +0 -3
- package/dist/extraction/languages/python.js +0 -56
- package/dist/extraction/languages/ruby.d.ts +0 -3
- package/dist/extraction/languages/ruby.js +0 -114
- package/dist/extraction/languages/rust.d.ts +0 -3
- package/dist/extraction/languages/rust.js +0 -109
- package/dist/extraction/languages/scala.d.ts +0 -3
- package/dist/extraction/languages/scala.js +0 -139
- package/dist/extraction/languages/swift.d.ts +0 -3
- package/dist/extraction/languages/swift.js +0 -91
- package/dist/extraction/languages/typescript.d.ts +0 -3
- package/dist/extraction/languages/typescript.js +0 -129
- package/dist/extraction/liquid-extractor.d.ts +0 -52
- package/dist/extraction/liquid-extractor.js +0 -313
- package/dist/extraction/parse-worker.d.ts +0 -8
- package/dist/extraction/parse-worker.js +0 -94
- package/dist/extraction/svelte-extractor.d.ts +0 -56
- package/dist/extraction/svelte-extractor.js +0 -272
- package/dist/extraction/tree-sitter-helpers.d.ts +0 -39
- package/dist/extraction/tree-sitter-helpers.js +0 -103
- package/dist/extraction/tree-sitter-types.d.ts +0 -191
- package/dist/extraction/tree-sitter-types.js +0 -10
- package/dist/extraction/tree-sitter.d.ts +0 -238
- package/dist/extraction/tree-sitter.js +0 -2430
- package/dist/extraction/vue-extractor.d.ts +0 -36
- package/dist/extraction/vue-extractor.js +0 -163
- package/dist/extraction/wasm/tree-sitter-c.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-cpp.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-dart.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-go.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-java.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-javascript.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-kotlin.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-php.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-python.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-ruby.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-rust.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-swift.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-tsx.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-typescript.wasm +0 -0
- package/dist/extraction/wasm-runtime-flags.d.ts +0 -46
- package/dist/extraction/wasm-runtime-flags.js +0 -105
- package/dist/graph/index.d.ts +0 -8
- package/dist/graph/index.js +0 -13
- package/dist/graph/queries.d.ts +0 -109
- package/dist/graph/queries.js +0 -366
- package/dist/graph/traversal.d.ts +0 -137
- package/dist/graph/traversal.js +0 -528
- package/dist/index.d.ts +0 -509
- package/dist/index.js +0 -800
- package/dist/installer/claude-md-template.d.ts +0 -19
- package/dist/installer/config-writer.d.ts +0 -29
- package/dist/installer/index.d.ts +0 -140
- package/dist/installer/instructions-template.d.ts +0 -30
- package/dist/installer/targets/claude.d.ts +0 -55
- package/dist/installer/targets/codex.d.ts +0 -18
- package/dist/installer/targets/cursor.d.ts +0 -35
- package/dist/installer/targets/hermes.d.ts +0 -18
- package/dist/installer/targets/opencode.d.ts +0 -30
- package/dist/installer/targets/registry.d.ts +0 -38
- package/dist/installer/targets/shared.d.ts +0 -92
- package/dist/installer/targets/toml.d.ts +0 -64
- package/dist/installer/targets/types.d.ts +0 -122
- package/dist/mcp/index.d.ts +0 -98
- package/dist/mcp/server-instructions.d.ts +0 -20
- package/dist/mcp/tools.d.ts +0 -269
- package/dist/mcp/transport.d.ts +0 -117
- package/dist/resolution/frameworks/cargo-workspace.d.ts +0 -20
- package/dist/resolution/frameworks/cargo-workspace.js +0 -225
- package/dist/resolution/frameworks/csharp.d.ts +0 -8
- package/dist/resolution/frameworks/csharp.js +0 -213
- package/dist/resolution/frameworks/drupal.d.ts +0 -51
- package/dist/resolution/frameworks/drupal.js +0 -335
- package/dist/resolution/frameworks/express.d.ts +0 -8
- package/dist/resolution/frameworks/express.js +0 -225
- package/dist/resolution/frameworks/go.d.ts +0 -8
- package/dist/resolution/frameworks/go.js +0 -158
- package/dist/resolution/frameworks/index.d.ts +0 -52
- package/dist/resolution/frameworks/index.js +0 -137
- package/dist/resolution/frameworks/java.d.ts +0 -8
- package/dist/resolution/frameworks/java.js +0 -177
- package/dist/resolution/frameworks/laravel.d.ts +0 -13
- package/dist/resolution/frameworks/laravel.js +0 -248
- package/dist/resolution/frameworks/nestjs.d.ts +0 -26
- package/dist/resolution/frameworks/nestjs.js +0 -374
- package/dist/resolution/frameworks/python.d.ts +0 -10
- package/dist/resolution/frameworks/python.js +0 -278
- package/dist/resolution/frameworks/react.d.ts +0 -8
- package/dist/resolution/frameworks/react.js +0 -272
- package/dist/resolution/frameworks/ruby.d.ts +0 -8
- package/dist/resolution/frameworks/ruby.js +0 -198
- package/dist/resolution/frameworks/rust.d.ts +0 -8
- package/dist/resolution/frameworks/rust.js +0 -207
- package/dist/resolution/frameworks/svelte.d.ts +0 -9
- package/dist/resolution/frameworks/svelte.js +0 -249
- package/dist/resolution/frameworks/swift.d.ts +0 -10
- package/dist/resolution/frameworks/swift.js +0 -376
- package/dist/resolution/frameworks/vue.d.ts +0 -9
- package/dist/resolution/frameworks/vue.js +0 -306
- package/dist/resolution/import-resolver.d.ts +0 -61
- package/dist/resolution/import-resolver.js +0 -663
- package/dist/resolution/index.d.ts +0 -118
- package/dist/resolution/index.js +0 -744
- package/dist/resolution/lru-cache.d.ts +0 -24
- package/dist/resolution/lru-cache.js +0 -62
- package/dist/resolution/name-matcher.d.ts +0 -50
- package/dist/resolution/name-matcher.js +0 -384
- package/dist/resolution/path-aliases.d.ts +0 -72
- package/dist/resolution/path-aliases.js +0 -238
- package/dist/resolution/strip-comments.d.ts +0 -40
- package/dist/resolution/strip-comments.js +0 -441
- package/dist/resolution/types.d.ts +0 -181
- package/dist/resolution/types.js +0 -8
- package/dist/search/query-parser.d.ts +0 -61
- package/dist/search/query-parser.js +0 -177
- package/dist/search/query-utils.d.ts +0 -59
- package/dist/search/query-utils.js +0 -383
- package/dist/sync/git-hooks.d.ts +0 -54
- package/dist/sync/git-hooks.js +0 -223
- package/dist/sync/index.d.ts +0 -25
- package/dist/sync/index.js +0 -28
- package/dist/sync/watch-policy.d.ts +0 -51
- package/dist/sync/watch-policy.js +0 -124
- package/dist/sync/watcher.d.ts +0 -83
- package/dist/sync/watcher.js +0 -192
- package/dist/types.d.ts +0 -433
- package/dist/types.js +0 -75
- package/dist/ui/glyphs.d.ts +0 -42
- package/dist/ui/shimmer-progress.d.ts +0 -11
- package/dist/ui/shimmer-worker.d.ts +0 -2
- package/dist/ui/types.d.ts +0 -20
- package/dist/utils.d.ts +0 -231
- package/dist/utils.js +0 -549
|
@@ -1,278 +0,0 @@
|
|
|
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
|
|
@@ -1,272 +0,0 @@
|
|
|
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
|