# NestJS Fundamentals (Part 1)

## 1. NestJS Is Built On Top of Express (or Fastify)

NestJS is not a replacement for Express — by default, a NestJS app runs on an Express instance underneath (Fastify is a drop-in alternative adapter). What NestJS adds is an **opinionated architectural layer** on top: modules, controllers, and providers, wired together with decorators and a built-in dependency-injection container. Where `01-express_fundamentals/` showed routes registered imperatively (`app.get(path, handler)`), NestJS expresses the same routing declaratively via decorators on classes.

```ts
import { Controller, Get } from "@nestjs/common";

@Controller("users")
class UsersController {
  @Get()
  findAll() {
    return [{ id: "1", name: "Ana" }];
  }
}
```

Under the hood, when the app bootstraps, NestJS reads these decorators via reflection and registers the equivalent of `app.get("/users", ...)` on the underlying Express instance — the decorators are metadata, not magic; something still has to translate `@Controller("users")` + `@Get()` into an actual route registration, and that something is NestJS's own bootstrap process.

## 2. The Three Core Building Blocks

```
Module      -- groups related controllers + providers into a cohesive unit
Controller  -- handles incoming requests, delegates to providers, shapes the response
Provider    -- (most commonly a "service") holds business logic / data access,
               injectable into controllers or other providers
```

```ts
import { Injectable, Controller, Get, Module } from "@nestjs/common";

@Injectable()
class UsersService {
  findAll() {
    return [{ id: "1", name: "Ana" }];
  }
}

@Controller("users")
class UsersController {
  constructor(private readonly usersService: UsersService) {} // injected, not `new`'d

  @Get()
  findAll() {
    return this.usersService.findAll(); // controller delegates, doesn't hold logic itself
  }
}

@Module({
  controllers: [UsersController],
  providers: [UsersService],
})
class UsersModule {}
```

This is the thin-controller principle from `01-express_fundamentals/` Common Pitfall 5, now enforced by the framework's own structure rather than left as a convention to remember — `UsersController` never touches data directly, it asks `UsersService` for it. The dedicated `10-services_and_repositories/` topic in this group covers the service/repository split in depth; NestJS's provider system is what makes that split mechanically easy to wire up.

## 3. Decorators Are Metadata, Not Behavior

`@Controller("users")`, `@Get()`, `@Injectable()` don't themselves *do* anything at the moment the class is defined — they attach metadata to the class (via `reflect-metadata` under the hood) that NestJS's bootstrap process reads later, when building the actual application. This is why a `UsersController` class with no `@Module` ever referencing it is simply never wired up — the decorators alone don't register anything; only being listed in a `@Module({ controllers: [...] })` array makes NestJS's bootstrap discover and instantiate it.

## 4. `@Module()` as the Unit of Organization

A real NestJS app is a tree of modules, each `@Module({ imports, controllers, providers, exports })`:

- `controllers` — request handlers this module owns
- `providers` — injectable classes this module owns (and makes available to its own controllers/providers)
- `imports` — other modules whose **exported** providers this module wants to use
- `exports` — which of this module's own providers other modules are allowed to import

```ts
@Module({
  imports: [DatabaseModule], // to use DatabaseModule's exported providers
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService], // so OTHER modules can inject UsersService too
})
class UsersModule {}
```

A provider not listed in `exports` is private to its own module — this is a deliberate encapsulation boundary, not an oversight; it's how a large NestJS app avoids every service being implicitly globally available.

## 5. Route Parameters and the Request Object

```ts
import { Controller, Get, Param, Query, Body, Post } from "@nestjs/common";

@Controller("users")
class UsersController {
  @Get(":id")
  findOne(@Param("id") id: string) { // equivalent to req.params.id in Express
    return { id };
  }

  @Get()
  findAll(@Query("limit") limit?: string) { // equivalent to req.query.limit
    return { limit };
  }

  @Post()
  create(@Body() body: { name: string }) { // equivalent to req.body
    return { created: body.name };
  }
}
```

Every one of these decorators is a thin, typed wrapper around exactly the same `req.params`/`req.query`/`req.body` covered in `01-express_fundamentals/` sections 3 and 5 — NestJS is not inventing a new request model, it's giving you a more structured, dependency-injectable way to pull the same data out of the same underlying Express request object.

## Common Pitfalls

1. **Forgetting to register a controller or provider in its `@Module`.** The decorators alone don't wire anything up — an unregistered `@Controller` class is simply never instantiated, silently, with no error.
2. **Forgetting `exports` on a provider another module needs.** `imports: [SomeModule]` only gives you access to what `SomeModule` explicitly `exports` — importing the module doesn't expose everything inside it.
3. **Putting business logic directly in a controller method** instead of delegating to an injected service — defeats the entire point of the controller/provider split (section 2).
4. **Assuming decorators run application logic at class-definition time.** They only attach metadata; nothing happens until NestJS's bootstrap reads it (section 3) — a common source of confusion when debugging why "nothing happened" even though the decorator is clearly present in the code.

## Quick Reference

```
@Module({ controllers, providers, imports, exports })  -- organizational unit
@Controller(prefix)  -- class handles requests under /prefix
@Get()/@Post()/@Put()/@Delete()(path?)  -- method-level route registration
@Injectable()  -- marks a class as available for dependency injection
@Param("x") / @Query("x") / @Body()  -- typed wrappers around req.params/query/body
constructor(private readonly svc: SomeService) {}  -- DI: NestJS instantiates and injects it
exports: [...]  -- only these providers are usable by OTHER modules that import this one
```
