Skip to content

Commit 4b3a5fa

Browse files
♻️ Clean up routerResolver with extracted helpers and context object (#113)
1 parent 3768e77 commit 4b3a5fa

File tree

1 file changed

+54
-105
lines changed

1 file changed

+54
-105
lines changed

src/core/routerResolver.ts

Lines changed: 54 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ import type { Parser } from "./parser"
1212

1313
export type { RouterNode }
1414

15+
interface ResolutionContext {
16+
projectRootUri: string
17+
parser: Parser
18+
fs: FileSystem
19+
visited: Set<string>
20+
}
21+
1522
/**
1623
* Finds the main FastAPI app or APIRouter in the list of routers.
1724
* If targetVariable is specified, only returns the router with that variable name.
@@ -55,6 +62,39 @@ function createRouterNode(
5562
}
5663
}
5764

65+
async function processIncludeRouters(
66+
analysis: FileAnalysis,
67+
ownerRouter: RouterNode,
68+
currentFileUri: string,
69+
ctx: ResolutionContext,
70+
): Promise<void> {
71+
const includes = analysis.includeRouters.filter(
72+
(inc) => inc.owner === ownerRouter.variableName,
73+
)
74+
for (const include of includes) {
75+
log(
76+
`Resolving include_router: ${include.router} (prefix: ${include.prefix || "none"})`,
77+
)
78+
const childRouter = await resolveRouterReference(
79+
include.router,
80+
analysis,
81+
currentFileUri,
82+
ctx,
83+
)
84+
if (childRouter) {
85+
// Merge tags from include_router call with the router's own tags
86+
if (include.tags.length > 0) {
87+
childRouter.tags = [...new Set([...childRouter.tags, ...include.tags])]
88+
}
89+
ownerRouter.children.push({
90+
router: childRouter,
91+
prefix: include.prefix,
92+
tags: include.tags,
93+
})
94+
}
95+
}
96+
}
97+
5898
/**
5999
* Builds a router graph starting from the given entry file.
60100
* If targetVariable is specified, only that specific app/router will be used.
@@ -68,10 +108,7 @@ export async function buildRouterGraph(
68108
): Promise<RouterNode | null> {
69109
return buildRouterGraphInternal(
70110
entryFileUri,
71-
parser,
72-
projectRootUri,
73-
fs,
74-
new Set(),
111+
{ projectRootUri, parser, fs, visited: new Set() },
75112
targetVariable,
76113
)
77114
}
@@ -81,12 +118,10 @@ export async function buildRouterGraph(
81118
*/
82119
async function buildRouterGraphInternal(
83120
entryFileUri: string,
84-
parser: Parser,
85-
projectRootUri: string,
86-
fs: FileSystem,
87-
visited: Set<string>,
121+
ctx: ResolutionContext,
88122
targetVariable?: string,
89123
): Promise<RouterNode | null> {
124+
const { projectRootUri, parser, fs, visited } = ctx
90125
// Check if file exists
91126
if (!(await fs.exists(entryFileUri))) {
92127
log(`File not found: "${entryFileUri}"`)
@@ -174,42 +209,15 @@ async function buildRouterGraphInternal(
174209
const rootRouter = createRouterNode(appRouter, appRoutes, resolvedEntryUri)
175210

176211
// Process include_router calls to find child routers
177-
for (const include of analysis.includeRouters) {
178-
log(
179-
`Resolving include_router: ${include.router} (prefix: ${include.prefix || "none"})`,
180-
)
181-
const childRouter = await resolveRouterReference(
182-
include.router,
183-
analysis,
184-
resolvedEntryUri,
185-
projectRootUri,
186-
parser,
187-
fs,
188-
visited,
189-
)
190-
if (childRouter) {
191-
// Merge tags from include_router call with the router's own tags
192-
if (include.tags.length > 0) {
193-
childRouter.tags = [...new Set([...childRouter.tags, ...include.tags])]
194-
}
195-
rootRouter.children.push({
196-
router: childRouter,
197-
prefix: include.prefix,
198-
tags: include.tags,
199-
})
200-
}
201-
}
212+
await processIncludeRouters(analysis, rootRouter, resolvedEntryUri, ctx)
202213

203214
// Process mount() calls for subapps
204215
for (const mount of analysis.mounts) {
205216
const childRouter = await resolveRouterReference(
206217
mount.app,
207218
analysis,
208219
resolvedEntryUri,
209-
projectRootUri,
210-
parser,
211-
fs,
212-
visited,
220+
ctx,
213221
)
214222
if (childRouter) {
215223
rootRouter.children.push({
@@ -234,11 +242,9 @@ async function resolveRouterReference(
234242
reference: string,
235243
analysis: FileAnalysis,
236244
currentFileUri: string,
237-
projectRootUri: string,
238-
parser: Parser,
239-
fs: FileSystem,
240-
visited: Set<string>,
245+
ctx: ResolutionContext,
241246
): Promise<RouterNode | null> {
247+
const { projectRootUri, parser, fs, visited } = ctx
242248
const parts = reference.split(".")
243249
const moduleName = parts[0]
244250
// For dotted references like "api_routes.router", extract the attribute name
@@ -258,35 +264,7 @@ async function resolveRouterReference(
258264
)
259265

260266
// Process include_router calls owned by this router (nested routers)
261-
const routerIncludes = analysis.includeRouters.filter(
262-
(inc) => inc.owner === moduleName,
263-
)
264-
for (const include of routerIncludes) {
265-
log(
266-
`Resolving nested include_router: ${include.router} (owner: ${moduleName}, prefix: ${include.prefix || "none"})`,
267-
)
268-
const childRouter = await resolveRouterReference(
269-
include.router,
270-
analysis,
271-
currentFileUri,
272-
projectRootUri,
273-
parser,
274-
fs,
275-
visited,
276-
)
277-
if (childRouter) {
278-
if (include.tags.length > 0) {
279-
childRouter.tags = [
280-
...new Set([...childRouter.tags, ...include.tags]),
281-
]
282-
}
283-
routerNode.children.push({
284-
router: childRouter,
285-
prefix: include.prefix,
286-
tags: include.tags,
287-
})
288-
}
289-
}
267+
await processIncludeRouters(analysis, routerNode, currentFileUri, ctx)
290268

291269
return routerNode
292270
}
@@ -362,46 +340,17 @@ async function resolveRouterReference(
362340
)
363341

364342
// Process include_router calls owned by this router (nested routers)
365-
const routerIncludes = importedAnalysis.includeRouters.filter(
366-
(inc) => inc.owner === attributeName,
343+
await processIncludeRouters(
344+
importedAnalysis,
345+
routerNode,
346+
importedFileUri,
347+
ctx,
367348
)
368-
for (const include of routerIncludes) {
369-
log(
370-
`Resolving nested include_router: ${include.router} (owner: ${attributeName}, prefix: ${include.prefix || "none"})`,
371-
)
372-
const childRouter = await resolveRouterReference(
373-
include.router,
374-
importedAnalysis,
375-
importedFileUri,
376-
projectRootUri,
377-
parser,
378-
fs,
379-
visited,
380-
)
381-
if (childRouter) {
382-
if (include.tags.length > 0) {
383-
childRouter.tags = [
384-
...new Set([...childRouter.tags, ...include.tags]),
385-
]
386-
}
387-
routerNode.children.push({
388-
router: childRouter,
389-
prefix: include.prefix,
390-
tags: include.tags,
391-
})
392-
}
393-
}
394349

395350
return routerNode
396351
}
397352
// If not found as a router, fall through to try building from file
398353
}
399354

400-
return buildRouterGraphInternal(
401-
importedFileUri,
402-
parser,
403-
projectRootUri,
404-
fs,
405-
visited,
406-
)
355+
return buildRouterGraphInternal(importedFileUri, ctx)
407356
}

0 commit comments

Comments
 (0)