feat(graph): add Next.js App Router route resolver - #179
Conversation
|
Thanks @abhinav-phi , this is a clean, well-scoped resolver. It follows the Express pattern, stays additive, and the tests line up with #95. I ran the resolver suites (all green, Express unaffected) and then real Must fix1. A repeated handler declaration fails the whole graph build
// app/api/x/route.ts
export function GET(a: Request): Response;
export function GET(a: Request, b: unknown): Response;
export function GET(a: Request, b?: unknown): Response { return new Response(); }A handler left inside a block comment does the same. Since a route module can only export one 2. Route paths are wrong in monorepos
The first reproduces end to end, and Should fix3. Typed
|
Translate file-based route modules into route nodes and connect exported HTTP handler functions without modeling the full Next.js routing system. The resolver recognizes app/**/route.ts|js including src/app roots, emits one route node per exported HTTP handler (GET through HEAD, declared as functions or arrow-function consts), and derives the URL path from the route file's directory. Dynamic segment text such as [id] and catch-alls such as [...slug] are preserved verbatim; route groups (marketing) are dropped the way Next itself resolves them. Detection keys on the next dependency in package.json or the presence of route files in the tree. Same-file handlers resolve only when unambiguous; missing or duplicate handlers stay unresolved. Pages Router, route groups' URL composition, rewrites, middleware, and server components stay out of scope. No identity, reconciliation, schema, or drift-semantics changes. Resolves mex-memory#95
- At most one route node per method per file. A route module can export
each verb once, but TypeScript overloads and handlers left in block
comments used to emit colliding node ids and fail the whole build
(Graph staging invariant: duplicate node id).
- deriveRoutePath locates the App Router root as a path segment, not a
substring: indexOf('app') turned apps/web/app/api/orders/route.ts
into /s/web/app/api/orders. Segment matching fixes monorepos
(apps/web, packages/webapp) with or without a src/ root.
- Typed const handlers (export const GET: RouteHandler = ...) now bind:
the name may carry an annotation before the initializer.
- Private folders (_lib) are dropped from derived paths like route
groups, matching Next's own routing.
- Edge label moves to nextjs-route-handler at confidence 0.8, matching
Express's evidence class; detection comment now records why route
files are an additional signal (root-only package.json in monorepos).
- The JavaScript fixture is valid JavaScript again.
- Changelog entry moved under [Unreleased] after the 0.8.1 release
absorbed the old section.
Addresses review on mex-memory#179
a37a046 to
8bb517a
Compare
|
All findings addressed. Must fixes
Should fix 3 — Smaller things — edge label is |
Resolves #95.
What
A bounded Next.js resolver following the
express.ts/flask.tspattern. It turns App Router route modules into route nodes and connects exported HTTP handler functions:app/**/route.tsandroute.js, includingsrc/approotsGET,POST,PUT,PATCH,DELETE,OPTIONS,HEAD— declared asexport async function GET()orexport const GET = async () => ...app/api/users/route.ts→/api/users[id]) and catch-alls ([...slug]) preserved verbatim; route groups ((marketing)) excluded from paths the way Next itself resolves themhelper()export is ignorednextdependency in package.json or the presence of route files in the tree (positive and negative cases tested)Out of scope, per the issue: Pages Router, route groups' URL composition nuances, parallel/intercepting routes, rewrites, middleware, server components, and any change to the TypeScript extractor or graph core. No identity, reconciliation, schema, or drift-semantics changes.
Tests
resolver-nextjs.test.ts(11): detection positive/negative (manifest and file-based), path derivation for both roots plus route groups/dynamic/catch-all segments and rejection of non-App-Router paths, function and arrow-function exports, JS route files, non-route files ignored, resolution and ambiguity, registry registration.resolver-nextjs-integration.test.ts(1): realrebuildGraphover a Next.js fixture — route nodes persist with the stablenextjs-routeidentity and both handlers resolve through framework edges.npm run typecheck,npm run buildpass; resolver suites green locally (the pre-existing Windows symlink/WAL failures intest/graph-integration.test.tsreproduce identically on cleanmainand are unrelated).