Skip to content

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

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

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

    windowsWindows-specific issues

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions