Skip to content

NestJS: @Controller/@Get/@Post routes are not extracted into Route nodes (decorator text is already captured) #2165

Open

Description

@deviddoe

Summary

NestJS controller routes are never turned into Route nodes. The information needed to build them is already in the graph — the decorator text is captured verbatim on the Method and Class nodes — but nothing converts it, so Route.method stays empty and the routes themselves are absent.

Same class of gap as #1041 (ASP.NET attribute routing), different framework.

Version: 0.10.8, windows-amd64 (standard variant)

Minimal reproduction

One file, src/cats.controller.ts, in an otherwise empty git repo:

import { Controller, Get, Post, Patch, Delete, Param, Body } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  @Get()
  list(): string[] { return []; }

  @Get(':id')
  findOne(@Param('id') id: string): string { return id; }

  @Post()
  create(@Body() body: unknown): unknown { return body; }

  @Patch(':id/rename')
  rename(@Param('id') id: string): string { return id; }

  @Delete(':id')
  remove(@Param('id') id: string): string { return id; }
}

Then index_repository(mode: "full").

Actual

MATCH (r:Route) RETURN count(*)   ->  0 rows

No Route nodes at all. But the raw decorators are all there:

MATCH (m:Method) RETURN m.name, m.decorators

list      ["@Get()"]
findOne   ["@Get(':id')"]
create    ["@Post()"]
rename    ["@Patch(':id/rename')"]
remove    ["@Delete(':id')"]

MATCH (c:Class) RETURN c.name, c.decorators

CatsController  ["@Controller('cats')"]

Expected

Five Route nodes, method and path resolved by joining the class prefix with each method's decorator:

method path
GET /cats
GET /cats/:id
POST /cats
PATCH /cats/:id/rename
DELETE /cats/:id

What Route currently contains instead

On a real NestJS + Next.js monorepo (417 files, ~4.8k nodes), Route is populated only from outbound HTTP call sites, not route definitions — 54 nodes, of which 53 have empty method, file_path and source:

/villa-batumi/assets/abc                                    <- a test fixture URL
https://challenges.cloudflare.com/turnstile/v0/siteverify   <- an external API
/assets/:asset.id/calendar                                  <- note: ":asset.id", from a template literal

Meanwhile the actual controllers in that repo carry exactly the decorator data needed, e.g. apps/api/src/bookings/bookings.controller.ts:

confirm       ["@Patch(':id/confirm')",       "@HttpCode(HttpStatus.OK)", "@Roles(...)"]
reject        ["@Patch(':id/reject')",        "@HttpCode(HttpStatus.OK)", "@Roles(...)"]
refundStatus  ["@Patch(':id/refund-status')", "@HttpCode(HttpStatus.OK)", "@Roles(...)"]

Why it matters

get_architecture(aspects: ["routes"]) lists paths with a blank method and a blank handler, so "which handler serves PATCH /bookings/:id/confirm" cannot be answered from the graph — the one question a route index exists to answer. Because Route.file_path is also empty, there is nothing to navigate to either.

Note

Two other things I hit on 0.9.0 are already fixed in 0.10.8 and are not part of this report: index_repository silently no-op'ing when a graph already existed, and EnvVar nodes not being produced. The new not_indexed_files / parse_partial / logfile reporting in 0.10.8 is a large improvement — it would have surfaced a 28-file blind spot that went unnoticed for weeks on the older build.

Activity

  1. petterip commented on Sep 16, 2026

    @petterip
    Contributor

    I would like to work on this NestJS extraction gap.

    The proposed fix would combine the @Controller prefix with each method’s HTTP decorator: @Controller('cats') plus @Get() becomes GET /cats, while @Patch(':id/rename') becomes PATCH /cats/:id/rename. These would use the existing route-node pass to create routes linked to their handler methods.

    I would add a regression using your CatsController reproduction, checking all five expected routes and their handler links.

    Global prefixes and versioning would remain separate work under #1428. I would also account for the route-ownership sequencing concern raised there before landing the change.

    Would you welcome a PR for this fix?

  2. added
    bugSomething isn't working
    priority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.
    parsing/qualityGraph extraction bugs, false positives, missing edges
    on Sep 19, 2026
  3. DeusData commented on Oct 19, 2026

    @DeusData
    Owner

    Thank you for the CatsController example, and @petterip for the focused handler-link proposal. The prefix composition and route ownership sequencing need a maintainer direction decision before I can give the requested PR go-ahead. The request remains distinct from global prefixes and versioning.

  4. DeusData commented on Oct 25, 2026

    @DeusData
    Owner

    Thank you for the route fixture and the focused contribution proposal. Handler ownership and prefix composition still need maintainer guidance before the requested PR go-ahead. Sorry for the delay; I’ll follow up soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingparsing/qualityGraph extraction bugs, false positives, missing edgespriority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.windowsWindows-specific issues

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions