Skip to content

Commit 9ee9f67

Browse files
committed
refactor(backend): extract analysis routes
1 parent 510335c commit 9ee9f67

1 file changed

Lines changed: 134 additions & 0 deletions

File tree

backend/routes/analysis.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
"""Analysis routes - dependencies, impact, insights, style."""
2+
from fastapi import APIRouter, HTTPException, Depends
3+
from pydantic import BaseModel
4+
5+
from dependencies import (
6+
dependency_analyzer, style_analyzer,
7+
get_repo_or_404
8+
)
9+
from services.input_validator import InputValidator
10+
from middleware.auth import require_auth, AuthContext
11+
12+
router = APIRouter(prefix="/api/repos", tags=["Analysis"])
13+
14+
15+
class ImpactRequest(BaseModel):
16+
repo_id: str
17+
file_path: str
18+
19+
20+
@router.get("/{repo_id}/dependencies")
21+
async def get_dependency_graph(
22+
repo_id: str,
23+
auth: AuthContext = Depends(require_auth)
24+
):
25+
"""Get dependency graph for repository."""
26+
try:
27+
repo = get_repo_or_404(repo_id, auth.user_id)
28+
29+
# Try cache first
30+
cached_graph = dependency_analyzer.load_from_cache(repo_id)
31+
if cached_graph:
32+
print(f"✅ Using cached dependency graph for {repo_id}")
33+
return {**cached_graph, "cached": True}
34+
35+
# Build fresh
36+
print(f"🔄 Building fresh dependency graph for {repo_id}")
37+
graph_data = dependency_analyzer.build_dependency_graph(repo["local_path"])
38+
dependency_analyzer.save_to_cache(repo_id, graph_data)
39+
40+
return {**graph_data, "cached": False}
41+
except Exception as e:
42+
raise HTTPException(status_code=500, detail=str(e))
43+
44+
45+
@router.post("/{repo_id}/impact")
46+
async def analyze_impact(
47+
repo_id: str,
48+
request: ImpactRequest,
49+
auth: AuthContext = Depends(require_auth)
50+
):
51+
"""Analyze impact of changing a file."""
52+
try:
53+
repo = get_repo_or_404(repo_id, auth.user_id)
54+
55+
# Validate file path
56+
valid_path, path_error = InputValidator.validate_file_path(
57+
request.file_path, repo["local_path"]
58+
)
59+
if not valid_path:
60+
raise HTTPException(status_code=400, detail=f"Invalid file path: {path_error}")
61+
62+
# Get or build graph
63+
graph_data = dependency_analyzer.load_from_cache(repo_id)
64+
if not graph_data:
65+
print(f"🔄 Building dependency graph for impact analysis")
66+
graph_data = dependency_analyzer.build_dependency_graph(repo["local_path"])
67+
dependency_analyzer.save_to_cache(repo_id, graph_data)
68+
69+
impact = dependency_analyzer.get_file_impact(
70+
repo["local_path"],
71+
request.file_path,
72+
graph_data
73+
)
74+
75+
return impact
76+
except Exception as e:
77+
raise HTTPException(status_code=500, detail=str(e))
78+
79+
80+
@router.get("/{repo_id}/insights")
81+
async def get_repository_insights(
82+
repo_id: str,
83+
auth: AuthContext = Depends(require_auth)
84+
):
85+
"""Get comprehensive insights about repository."""
86+
try:
87+
repo = get_repo_or_404(repo_id, auth.user_id)
88+
89+
# Get or build graph
90+
graph_data = dependency_analyzer.load_from_cache(repo_id)
91+
if not graph_data:
92+
print(f"🔄 Building dependency graph for insights")
93+
graph_data = dependency_analyzer.build_dependency_graph(repo["local_path"])
94+
dependency_analyzer.save_to_cache(repo_id, graph_data)
95+
96+
return {
97+
"repo_id": repo_id,
98+
"name": repo["name"],
99+
"graph_metrics": graph_data.get("metrics", {}),
100+
"total_files": len(graph_data.get("dependencies", {})),
101+
"total_dependencies": sum(
102+
len(deps) for deps in graph_data.get("dependencies", {}).values()
103+
),
104+
"status": repo["status"],
105+
"functions_indexed": repo["file_count"],
106+
"cached": bool(graph_data)
107+
}
108+
except Exception as e:
109+
raise HTTPException(status_code=500, detail=str(e))
110+
111+
112+
@router.get("/{repo_id}/style-analysis")
113+
async def get_style_analysis(
114+
repo_id: str,
115+
auth: AuthContext = Depends(require_auth)
116+
):
117+
"""Analyze code style and team patterns."""
118+
try:
119+
repo = get_repo_or_404(repo_id, auth.user_id)
120+
121+
# Try cache first
122+
cached_style = style_analyzer.load_from_cache(repo_id)
123+
if cached_style:
124+
print(f"✅ Using cached code style for {repo_id}")
125+
return {**cached_style, "cached": True}
126+
127+
# Analyze fresh
128+
print(f"🔄 Analyzing code style for {repo_id}")
129+
style_data = style_analyzer.analyze_repository_style(repo["local_path"])
130+
style_analyzer.save_to_cache(repo_id, style_data)
131+
132+
return {**style_data, "cached": False}
133+
except Exception as e:
134+
raise HTTPException(status_code=500, detail=str(e))

0 commit comments

Comments
 (0)