Endpoint Tracer
A VS Code extension that takes a backend endpoint URL and jumps you to the
NestJS controller and exact handler method that serves it — useful in large
codebases and monorepos where routes are assembled from several layers.
http://localhost:3000/users/list?search=
→ ListUsersController.listUsers
src/users/web/list-users.controller.ts:34
What it understands
A full route is composed of up to three layers, and the extension resolves all
of them statically (via the TypeScript AST — no running server required):
| Layer |
Source |
Example |
| RouterModule prefix |
RouterModule.register([{ path, module }]) |
billing/invoices |
| Controller prefix |
@Controller("...") |
orders |
| Method path |
@Get/@Post/@Put/@Patch/@Delete("...") |
/:orderId/items |
So GET /billing/invoices/orders/abc/items is traced to the right handler,
capturing orderId = abc.
It correctly handles:
- Module prefixes via
RouterModule (including nested children).
- Prefix routes and paths combined from different fragments (module +
controller + method), with slashes normalised.
- Path params —
:id in decorators and [id] folder segments are matched
against any value, and the captured values are shown.
- Same-named modules in different files — modules and controllers are
disambiguated by their resolved import file path, not by class name, so a
controller never inherits a prefix from an unrelated module that happens to
share a name.
- Multi-path decorators (
@Get(["a", "b"])) and @Controller({ path }) form.
- Query strings, hosts and verbs in the input are stripped/parsed:
GET http://localhost:3000/foo?x=1 → verb GET, path /foo.
Usage
Open your NestJS project as the workspace, then either:
- Click the Endpoint Tracer icon in the activity bar, paste an endpoint, and
press Trace endpoint (or
Enter). Click any result to open it at the
handler line.
- Run
Endpoint Tracer: Find Controller for Endpoint from the command
palette for a quick-pick flow.
If no route matches exactly, the closest partial matches (by leading path
segments) are shown instead.
Configuration
| Setting |
Default |
Description |
endpointTracer.sourceRoots |
["src", "apps/*/src", "libs/*/src", "packages/*/src"] |
Folders scanned for *.controller.ts / *.module.ts, relative to each workspace folder. A trailing * segment is expanded one level. The first existing root wins; the rest are fallbacks. Add your own layout here if it differs. |
endpointTracer.maxResults |
30 |
Max matches shown. |
The index builds on activation and rebuilds automatically when any
*.controller.ts / *.module.ts changes. Use Endpoint Tracer: Rebuild Route Index to force a refresh.
Develop
npm install
npm run compile # or: npm run watch
Press F5 to launch an Extension Development Host. The bundled Run Extension
launch config opens a sibling ../backend folder as the test workspace — edit
.vscode/launch.json to point it at any NestJS project you want to trace.
How it works
- Index — every
*.controller.ts is parsed for its @Controller path(s)
and HTTP-method decorators; every *.module.ts is parsed for its
controllers: [...] membership (expanding ...spread of local const
arrays) and any RouterModule.register prefixes. Imports are resolved to
absolute file paths so identically-named classes stay distinct.
- Resolve — prefixes flow module → controller (by file path), and each
handler becomes one or more fully-qualified routes.
- Match — the queried URL is normalised to segments and matched against the
route table segment-by-segment, with
:param segments acting as wildcards
and exact (literal) matches ranked above param-heavy ones.
Limitations
Matching is purely static path matching. It does not evaluate guards, a global
prefix set via app.setGlobalPrefix(...), controller-level API versioning
(@Controller({ version })), or routes registered dynamically at runtime.
License
MIT