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

Author: deviddoeCreated Sep 10, 2026Updated Sep 16, 2026
Labelswindows

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:

typescript
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.

Source: DeusData/codebase-memory-mcp