codegraph-engine 3.0.0__1-py3-none-any.whl
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.
- codegraph/__init__.py +37 -0
- codegraph/agent.py +26 -0
- codegraph/agent_brain.py +2212 -0
- codegraph/agent_capabilities.py +4058 -0
- codegraph/agent_rules.py +531 -0
- codegraph/api_drift.py +455 -0
- codegraph/architecture.py +371 -0
- codegraph/async_queue/__init__.py +50 -0
- codegraph/async_queue/detectors/__init__.py +48 -0
- codegraph/async_queue/detectors/celery.py +160 -0
- codegraph/async_queue/detectors/kafka.py +168 -0
- codegraph/async_queue/detectors/rabbitmq.py +116 -0
- codegraph/async_queue/detectors/redis.py +130 -0
- codegraph/async_queue/detectors/sqs.py +135 -0
- codegraph/async_queue/models.py +161 -0
- codegraph/async_queue/otel_models.py +74 -0
- codegraph/async_queue/otel_parser.py +337 -0
- codegraph/async_queue/reconciler.py +427 -0
- codegraph/async_queue/scanner.py +291 -0
- codegraph/async_queue/traversal.py +447 -0
- codegraph/audit.py +106 -0
- codegraph/binding_resolver.py +616 -0
- codegraph/branch_comparison.py +197 -0
- codegraph/cache.py +95 -0
- codegraph/change_impact.py +547 -0
- codegraph/cli.py +2436 -0
- codegraph/cli_output.py +205 -0
- codegraph/config.py +45 -0
- codegraph/constraints.py +238 -0
- codegraph/context.py +2182 -0
- codegraph/context_freshness.py +351 -0
- codegraph/database/__init__.py +72 -0
- codegraph/database/extractor.py +3651 -0
- codegraph/database/interrogation.py +1494 -0
- codegraph/database/models.py +310 -0
- codegraph/database/schema_drift.py +862 -0
- codegraph/epistemic.py +200 -0
- codegraph/errors.py +282 -0
- codegraph/evidence/__init__.py +15 -0
- codegraph/evidence/citations.py +418 -0
- codegraph/evidence_contract.py +486 -0
- codegraph/frameworks.py +960 -0
- codegraph/frameworks_nestjs.py +502 -0
- codegraph/frameworks_nextjs.py +337 -0
- codegraph/frameworks_react.py +457 -0
- codegraph/freshness.py +335 -0
- codegraph/frontend_html.py +109 -0
- codegraph/git.py +362 -0
- codegraph/git_state.py +545 -0
- codegraph/graph/__init__.py +46 -0
- codegraph/graph/models.py +56 -0
- codegraph/graph/traversal.py +1993 -0
- codegraph/indexing/__init__.py +24 -0
- codegraph/indexing/classifier.py +564 -0
- codegraph/indexing/indexer.py +2578 -0
- codegraph/indexing/models.py +427 -0
- codegraph/indexing/parser.py +3404 -0
- codegraph/indexing/pool.py +136 -0
- codegraph/indexing/scanner.py +211 -0
- codegraph/indexing/telemetry.py +326 -0
- codegraph/indexing/templates.py +418 -0
- codegraph/indexing/test_framework.py +116 -0
- codegraph/installer.py +1702 -0
- codegraph/interrogation.py +2355 -0
- codegraph/llm/__init__.py +3 -0
- codegraph/llm/base.py +15 -0
- codegraph/llm/context.py +20 -0
- codegraph/mcp/__init__.py +3 -0
- codegraph/mcp/server.py +1476 -0
- codegraph/mcp_diagnostics.py +882 -0
- codegraph/memory/__init__.py +3 -0
- codegraph/memory/store.py +46 -0
- codegraph/models.py +310 -0
- codegraph/monorepo.py +925 -0
- codegraph/observability.py +262 -0
- codegraph/optimizer.py +1014 -0
- codegraph/planner.py +417 -0
- codegraph/process_lifecycle.py +1153 -0
- codegraph/py.typed +1 -0
- codegraph/query_expansion.py +199 -0
- codegraph/ranking.py +408 -0
- codegraph/refactor/__init__.py +36 -0
- codegraph/refactor/models.py +114 -0
- codegraph/refactor/renamer.py +844 -0
- codegraph/refactor/transactions.py +414 -0
- codegraph/resolver.py +3968 -0
- codegraph/resources/__init__.py +46 -0
- codegraph/resources/cache.py +117 -0
- codegraph/resources/coalescer.py +83 -0
- codegraph/resources/debouncer.py +98 -0
- codegraph/resources/governor.py +219 -0
- codegraph/resources/monitor.py +102 -0
- codegraph/resources/policy.py +123 -0
- codegraph/retrieval_policy.py +320 -0
- codegraph/roblox.py +2174 -0
- codegraph/route_composer.py +363 -0
- codegraph/route_topology.py +172 -0
- codegraph/runtime/__init__.py +51 -0
- codegraph/runtime/collector.py +155 -0
- codegraph/runtime/db_watcher.py +191 -0
- codegraph/runtime/ingestor.py +692 -0
- codegraph/runtime/models.py +130 -0
- codegraph/runtime/port_inspector.py +304 -0
- codegraph/runtime/reconciliation.py +492 -0
- codegraph/runtime/runner.py +353 -0
- codegraph/runtime/trace_linker.py +175 -0
- codegraph/search/__init__.py +25 -0
- codegraph/search/hybrid.py +846 -0
- codegraph/search/semantic.py +28 -0
- codegraph/security/__init__.py +51 -0
- codegraph/security/paths.py +189 -0
- codegraph/security/redaction.py +633 -0
- codegraph/semantic_conflicts.py +270 -0
- codegraph/semantic_decorators.py +372 -0
- codegraph/structural_diff.py +542 -0
- codegraph/styles.py +144 -0
- codegraph/symbol_history.py +277 -0
- codegraph/target_resolver.py +348 -0
- codegraph/task.py +637 -0
- codegraph/tool_selection_eval.py +1158 -0
- codegraph/tsconfig.py +236 -0
- codegraph/ui/__init__.py +6 -0
- codegraph/ui/server.py +755 -0
- codegraph/watcher.py +323 -0
- codegraph_engine-3.0.0.dist-info/METADATA +859 -0
- codegraph_engine-3.0.0.dist-info/RECORD +130 -0
- codegraph_engine-3.0.0.dist-info/WHEEL +6 -0
- codegraph_engine-3.0.0.dist-info/entry_points.txt +2 -0
- codegraph_engine-3.0.0.dist-info/licenses/LICENSE +21 -0
- codegraph_engine-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
"""Deterministic Next.js App Router and Server Actions analyzer.
|
|
2
|
+
|
|
3
|
+
Features:
|
|
4
|
+
- App Router directory-derived route mapping (`app/**/route.ts` and `app/**/page.tsx`).
|
|
5
|
+
- Route group unwrapping: `app/(auth)/login/route.ts` -> `/login`.
|
|
6
|
+
- Dynamic segment normalization: `[id]` -> `{id}`, `[...slug]` -> `{slug}`, `[[...slug]]` -> `{slug}`.
|
|
7
|
+
- HTTP method route handlers: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`.
|
|
8
|
+
- Page routes: default exports from `page.tsx` mapped to `GET` routes.
|
|
9
|
+
- Server Actions detection:
|
|
10
|
+
- File-level `'use server'` marks all exported async functions as `SERVER_ACTION`.
|
|
11
|
+
- Function-level `'use server'` marks specific functions as `SERVER_ACTION`.
|
|
12
|
+
- Client Component hydration boundary detection: file-level `'use client'`.
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import re
|
|
17
|
+
from dataclasses import dataclass, field
|
|
18
|
+
|
|
19
|
+
from codegraph.frameworks import FrameworkEvidence, RouteDetection, normalize_route_path
|
|
20
|
+
from codegraph.indexing.models import BindingRef
|
|
21
|
+
|
|
22
|
+
_NEXT_ROUTE_METHODS = frozenset({
|
|
23
|
+
"GET",
|
|
24
|
+
"POST",
|
|
25
|
+
"PUT",
|
|
26
|
+
"DELETE",
|
|
27
|
+
"PATCH",
|
|
28
|
+
"OPTIONS",
|
|
29
|
+
"HEAD",
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
# Matches export (async) function NAME
|
|
33
|
+
_EXPORT_FUNC_RE = re.compile(
|
|
34
|
+
r"\bexport\s+(?:async\s+)?function\s+([A-Za-z_$][\w$]*)\s*\("
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Matches export const NAME = (async) (
|
|
38
|
+
_EXPORT_CONST_FUNC_RE = re.compile(
|
|
39
|
+
r"\bexport\s+const\s+([A-Za-z_$][\w$]*)\s*=\s*(?:async\s*)?(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Matches export default function/const
|
|
43
|
+
_EXPORT_DEFAULT_RE = re.compile(
|
|
44
|
+
r"\bexport\s+default\s+(?:async\s+)?(?:function\s*([A-Za-z_$][\w$]*)?|class\s*([A-Za-z_$][\w$]*)?|([A-Za-z_$][\w$]*))"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Function body scan for inline 'use server'
|
|
48
|
+
_INLINE_USE_SERVER_RE = re.compile(
|
|
49
|
+
r"(?:async\s+function\s+([A-Za-z_$][\w$]*)|(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*async)[\s\S]*?\{[\s\S]*?['\"`]use server['\"`]"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class NextjsAnalysisResult:
|
|
55
|
+
routes: list[RouteDetection] = field(default_factory=list)
|
|
56
|
+
evidence: list[FrameworkEvidence] = field(default_factory=list)
|
|
57
|
+
bindings: list[BindingRef] = field(default_factory=list)
|
|
58
|
+
server_actions: list[str] = field(default_factory=list)
|
|
59
|
+
is_client_component: bool = False
|
|
60
|
+
is_server_actions_file: bool = False
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def resolve_nextjs_route_path(file_path: str) -> tuple[str, str]:
|
|
64
|
+
"""Derive canonical URL route and normalized route from Next.js App Router file path.
|
|
65
|
+
|
|
66
|
+
Handles:
|
|
67
|
+
- Root and nested app dirs: `app/...` or `src/app/...`
|
|
68
|
+
- Route groups: `app/(dashboard)/invoices/page.tsx` -> `/invoices`
|
|
69
|
+
- Dynamic params: `[id]` -> `{id}`, `[...slug]` -> `{slug}`
|
|
70
|
+
"""
|
|
71
|
+
norm_path = file_path.replace("\\", "/").strip("/")
|
|
72
|
+
|
|
73
|
+
# Find where app/ or pages/ starts
|
|
74
|
+
app_idx = -1
|
|
75
|
+
for prefix in ("/src/app/", "src/app/", "/app/", "app/"):
|
|
76
|
+
idx = norm_path.find(prefix)
|
|
77
|
+
if idx != -1:
|
|
78
|
+
app_idx = idx + len(prefix)
|
|
79
|
+
break
|
|
80
|
+
|
|
81
|
+
if app_idx == -1:
|
|
82
|
+
# Fallback: check if path contains route.ts/page.tsx directly
|
|
83
|
+
subpath = norm_path.rsplit("/", 1)[0] if "/" in norm_path else ""
|
|
84
|
+
else:
|
|
85
|
+
subpath = norm_path[app_idx:]
|
|
86
|
+
if "/" in subpath:
|
|
87
|
+
subpath = subpath.rsplit("/", 1)[0]
|
|
88
|
+
else:
|
|
89
|
+
subpath = ""
|
|
90
|
+
|
|
91
|
+
# Split into path segments and strip route groups (parenthesized folders) and parallel routes (@)
|
|
92
|
+
raw_segments = subpath.split("/") if subpath else []
|
|
93
|
+
cleaned_segments: list[str] = []
|
|
94
|
+
for seg in raw_segments:
|
|
95
|
+
s = seg.strip()
|
|
96
|
+
if not s:
|
|
97
|
+
continue
|
|
98
|
+
# Route groups like (auth), (dashboard) are omitted from route path
|
|
99
|
+
if s.startswith("(") and s.endswith(")"):
|
|
100
|
+
continue
|
|
101
|
+
# Parallel slots like @modal are omitted from route path
|
|
102
|
+
if s.startswith("@"):
|
|
103
|
+
continue
|
|
104
|
+
cleaned_segments.append(s)
|
|
105
|
+
|
|
106
|
+
raw_route = "/" + "/".join(cleaned_segments) if cleaned_segments else "/"
|
|
107
|
+
normalized = normalize_route_path(raw_route, "nextjs")
|
|
108
|
+
return raw_route, normalized
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def analyze_nextjs_file(
|
|
112
|
+
content: str,
|
|
113
|
+
file_path: str,
|
|
114
|
+
module: str,
|
|
115
|
+
) -> NextjsAnalysisResult:
|
|
116
|
+
"""Analyze a TypeScript/JavaScript file for Next.js App Router routes, Server Actions, and Client Components."""
|
|
117
|
+
res = NextjsAnalysisResult()
|
|
118
|
+
if not content:
|
|
119
|
+
return res
|
|
120
|
+
|
|
121
|
+
norm_path = file_path.replace("\\", "/").lower()
|
|
122
|
+
is_route_file = (
|
|
123
|
+
norm_path.endswith("/route.ts")
|
|
124
|
+
or norm_path.endswith("/route.js")
|
|
125
|
+
or norm_path.endswith("/route.mjs")
|
|
126
|
+
or norm_path == "route.ts"
|
|
127
|
+
or norm_path == "route.js"
|
|
128
|
+
)
|
|
129
|
+
is_page_file = (
|
|
130
|
+
norm_path.endswith("/page.tsx")
|
|
131
|
+
or norm_path.endswith("/page.jsx")
|
|
132
|
+
or norm_path.endswith("/page.ts")
|
|
133
|
+
or norm_path.endswith("/page.js")
|
|
134
|
+
or norm_path == "page.tsx"
|
|
135
|
+
or norm_path == "page.jsx"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
lines = content.splitlines()
|
|
139
|
+
|
|
140
|
+
# 1. Inspect top directives: 'use server' or 'use client'
|
|
141
|
+
top_use_server = False
|
|
142
|
+
for line_idx, line in enumerate(lines[:15], start=1):
|
|
143
|
+
stripped = line.strip()
|
|
144
|
+
if not stripped or stripped.startswith(("//", "/*", "*")):
|
|
145
|
+
continue
|
|
146
|
+
if stripped in ("'use server';", '"use server";', "'use server'", '"use server"'):
|
|
147
|
+
top_use_server = True
|
|
148
|
+
res.is_server_actions_file = True
|
|
149
|
+
res.evidence.append(
|
|
150
|
+
FrameworkEvidence(
|
|
151
|
+
framework="nextjs",
|
|
152
|
+
construct_type="SERVER_ACTION_FILE",
|
|
153
|
+
file_path=file_path,
|
|
154
|
+
line=line_idx,
|
|
155
|
+
column=line.find(stripped),
|
|
156
|
+
evidence="File-level 'use server' directive",
|
|
157
|
+
)
|
|
158
|
+
)
|
|
159
|
+
break
|
|
160
|
+
elif stripped in ("'use client';", '"use client";', "'use client'", '"use client"'):
|
|
161
|
+
res.is_client_component = True
|
|
162
|
+
res.evidence.append(
|
|
163
|
+
FrameworkEvidence(
|
|
164
|
+
framework="nextjs",
|
|
165
|
+
construct_type="CLIENT_COMPONENT",
|
|
166
|
+
file_path=file_path,
|
|
167
|
+
line=line_idx,
|
|
168
|
+
column=line.find(stripped),
|
|
169
|
+
evidence="Client component hydration boundary ('use client')",
|
|
170
|
+
)
|
|
171
|
+
)
|
|
172
|
+
break
|
|
173
|
+
# First non-comment statement that is not a directive terminates directive search
|
|
174
|
+
if not stripped.startswith(("import ", "'use ", '"use ')):
|
|
175
|
+
break
|
|
176
|
+
|
|
177
|
+
# 2. Server Actions:
|
|
178
|
+
# If file has file-level 'use server', any exported async function is a Server Action
|
|
179
|
+
if top_use_server:
|
|
180
|
+
for line_idx, line in enumerate(lines, start=1):
|
|
181
|
+
for m in _EXPORT_FUNC_RE.finditer(line):
|
|
182
|
+
fn_name = m.group(1)
|
|
183
|
+
res.server_actions.append(fn_name)
|
|
184
|
+
res.evidence.append(
|
|
185
|
+
FrameworkEvidence(
|
|
186
|
+
framework="nextjs",
|
|
187
|
+
construct_type="SERVER_ACTION",
|
|
188
|
+
file_path=file_path,
|
|
189
|
+
line=line_idx,
|
|
190
|
+
column=m.start(),
|
|
191
|
+
evidence=f"Next.js Server Action: export async function {fn_name}",
|
|
192
|
+
)
|
|
193
|
+
)
|
|
194
|
+
res.bindings.append(
|
|
195
|
+
BindingRef(
|
|
196
|
+
target_name=f"{module}.{fn_name}",
|
|
197
|
+
source_expr=fn_name,
|
|
198
|
+
file_path=file_path,
|
|
199
|
+
line=line_idx,
|
|
200
|
+
scope="",
|
|
201
|
+
expr_kind="SERVER_ACTION",
|
|
202
|
+
base_expr="nextjs_server_action",
|
|
203
|
+
attr_name=fn_name,
|
|
204
|
+
)
|
|
205
|
+
)
|
|
206
|
+
for m in _EXPORT_CONST_FUNC_RE.finditer(line):
|
|
207
|
+
fn_name = m.group(1)
|
|
208
|
+
res.server_actions.append(fn_name)
|
|
209
|
+
res.evidence.append(
|
|
210
|
+
FrameworkEvidence(
|
|
211
|
+
framework="nextjs",
|
|
212
|
+
construct_type="SERVER_ACTION",
|
|
213
|
+
file_path=file_path,
|
|
214
|
+
line=line_idx,
|
|
215
|
+
column=m.start(),
|
|
216
|
+
evidence=f"Next.js Server Action: export const {fn_name} = async ...",
|
|
217
|
+
)
|
|
218
|
+
)
|
|
219
|
+
res.bindings.append(
|
|
220
|
+
BindingRef(
|
|
221
|
+
target_name=f"{module}.{fn_name}",
|
|
222
|
+
source_expr=fn_name,
|
|
223
|
+
file_path=file_path,
|
|
224
|
+
line=line_idx,
|
|
225
|
+
scope="",
|
|
226
|
+
expr_kind="SERVER_ACTION",
|
|
227
|
+
base_expr="nextjs_server_action",
|
|
228
|
+
attr_name=fn_name,
|
|
229
|
+
)
|
|
230
|
+
)
|
|
231
|
+
else:
|
|
232
|
+
# Check for inline 'use server' inside function bodies
|
|
233
|
+
for m in _INLINE_USE_SERVER_RE.finditer(content):
|
|
234
|
+
fn_name = m.group(1) or m.group(2)
|
|
235
|
+
if fn_name:
|
|
236
|
+
line_no = content[: m.start()].count("\n") + 1
|
|
237
|
+
res.server_actions.append(fn_name)
|
|
238
|
+
res.evidence.append(
|
|
239
|
+
FrameworkEvidence(
|
|
240
|
+
framework="nextjs",
|
|
241
|
+
construct_type="SERVER_ACTION",
|
|
242
|
+
file_path=file_path,
|
|
243
|
+
line=line_no,
|
|
244
|
+
column=None,
|
|
245
|
+
evidence=f"Next.js inline Server Action {fn_name}",
|
|
246
|
+
)
|
|
247
|
+
)
|
|
248
|
+
res.bindings.append(
|
|
249
|
+
BindingRef(
|
|
250
|
+
target_name=f"{module}.{fn_name}",
|
|
251
|
+
source_expr=fn_name,
|
|
252
|
+
file_path=file_path,
|
|
253
|
+
line=line_no,
|
|
254
|
+
scope="",
|
|
255
|
+
expr_kind="SERVER_ACTION",
|
|
256
|
+
base_expr="nextjs_server_action",
|
|
257
|
+
attr_name=fn_name,
|
|
258
|
+
)
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
# 3. Route Handlers: app/**/route.ts
|
|
262
|
+
if is_route_file:
|
|
263
|
+
raw_route, norm_route = resolve_nextjs_route_path(file_path)
|
|
264
|
+
for line_idx, line in enumerate(lines, start=1):
|
|
265
|
+
# Check function exports
|
|
266
|
+
for m in _EXPORT_FUNC_RE.finditer(line):
|
|
267
|
+
method_name = m.group(1).upper()
|
|
268
|
+
if method_name in _NEXT_ROUTE_METHODS:
|
|
269
|
+
res.routes.append(
|
|
270
|
+
RouteDetection(
|
|
271
|
+
framework="nextjs",
|
|
272
|
+
http_method=method_name,
|
|
273
|
+
route_path=raw_route,
|
|
274
|
+
normalized_route=norm_route,
|
|
275
|
+
handler_name=method_name,
|
|
276
|
+
handler_canonical_id=f"{module}.{method_name}",
|
|
277
|
+
file_path=file_path,
|
|
278
|
+
line=line_idx,
|
|
279
|
+
column=m.start(),
|
|
280
|
+
confidence="HIGH",
|
|
281
|
+
resolution_status="RESOLVED",
|
|
282
|
+
evidence=f"Next.js App Router HTTP handler {method_name} in {file_path}",
|
|
283
|
+
module=module,
|
|
284
|
+
router_name="export",
|
|
285
|
+
)
|
|
286
|
+
)
|
|
287
|
+
# Check const exports
|
|
288
|
+
for m in _EXPORT_CONST_FUNC_RE.finditer(line):
|
|
289
|
+
method_name = m.group(1).upper()
|
|
290
|
+
if method_name in _NEXT_ROUTE_METHODS:
|
|
291
|
+
res.routes.append(
|
|
292
|
+
RouteDetection(
|
|
293
|
+
framework="nextjs",
|
|
294
|
+
http_method=method_name,
|
|
295
|
+
route_path=raw_route,
|
|
296
|
+
normalized_route=norm_route,
|
|
297
|
+
handler_name=method_name,
|
|
298
|
+
handler_canonical_id=f"{module}.{method_name}",
|
|
299
|
+
file_path=file_path,
|
|
300
|
+
line=line_idx,
|
|
301
|
+
column=m.start(),
|
|
302
|
+
confidence="HIGH",
|
|
303
|
+
resolution_status="RESOLVED",
|
|
304
|
+
evidence=f"Next.js App Router HTTP handler {method_name} in {file_path}",
|
|
305
|
+
module=module,
|
|
306
|
+
router_name="export",
|
|
307
|
+
)
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
# 4. Page Routes: app/**/page.tsx
|
|
311
|
+
elif is_page_file:
|
|
312
|
+
raw_route, norm_route = resolve_nextjs_route_path(file_path)
|
|
313
|
+
for line_idx, line in enumerate(lines, start=1):
|
|
314
|
+
page_m = _EXPORT_DEFAULT_RE.search(line)
|
|
315
|
+
if page_m:
|
|
316
|
+
fn_name = page_m.group(1) or page_m.group(2) or page_m.group(3) or "default"
|
|
317
|
+
res.routes.append(
|
|
318
|
+
RouteDetection(
|
|
319
|
+
framework="nextjs",
|
|
320
|
+
http_method="GET",
|
|
321
|
+
route_path=raw_route,
|
|
322
|
+
normalized_route=norm_route,
|
|
323
|
+
handler_name=fn_name,
|
|
324
|
+
handler_canonical_id=f"{module}.{fn_name}",
|
|
325
|
+
file_path=file_path,
|
|
326
|
+
line=line_idx,
|
|
327
|
+
column=page_m.start(),
|
|
328
|
+
confidence="HIGH",
|
|
329
|
+
resolution_status="RESOLVED",
|
|
330
|
+
evidence=f"Next.js App Router Page route GET {raw_route} ({fn_name})",
|
|
331
|
+
module=module,
|
|
332
|
+
router_name="page",
|
|
333
|
+
)
|
|
334
|
+
)
|
|
335
|
+
break
|
|
336
|
+
|
|
337
|
+
return res
|