🚀 Building Toy: REST API in NestJS
Tags: javascript, typescript, beginners, node
Published: 2024-06-01 10:40:00

Hey everyone! 👋

🤔 Ever wondered how to start building backend applications? Let's dive into creating your first to-do app with NestJS and Node.js!

Whether you're new to backend development or just brushing up on your skills, this guide is perfect for you. We'll start with a basic To-Do application and even integrate Swagger for live API documentation. 📝

🔧 **What You’ll Learn:**
- Set up a basic To-Do application using NestJS.
- Integrate Swagger to create interactive API documentation.
- Understand the basics of Node.js and NestJS frameworks.

💡 **Why Build a Toy To-Do App?**
It’s a fantastic exercise for beginners aiming to learn about backend development. Plus, the integration of Swagger enhances your app with interactive API documentation that can be tested directly from your browser.

### Getting Started

#### Installing Node.js v20.9.0

Ensure you have the latest LTS version of Node.js installed using nvm:

```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
nvm install 20.9.0
nvm use 20.9.0
```

#### Setting Up the NestJS Project

**Install the NestJS CLI:**
```bash
npm i -g @nestjs/cli
nest new todo-app
cd todo-app
```

**Create a To-Do Module:**
```bash
nest generate module todos
nest generate service todos
nest generate controller todos
```
   These commands set up the basic structure for managing To-Do items.

### Building the Application

#### Step 1: Define the To-Do Model

Create a `todo.model.ts` in the `src/todos` folder:

```typescript
export class Todo {
  id: string;
  title: string;
  description?: string;
  isCompleted: boolean;
}
```

#### Step 2: Create a DTO

Define the structure for creating new To-Do items with `create-todo.dto.ts`:

```typescript
export class CreateTodoDto {
  title: string;
  description?: string;
}
```

#### Step 3: Implement the Service

Install UUID:

```bash
npm install uuid
```

Services in NestJS handle business logic. Here’s how you set up `todos.service.ts`:

```typescript
import { Injectable } from '@nestjs/common';
import { Todo } from './todo.model';
import { CreateTodoDto } from './create-todo.dto';
import { v4 as uuidv4 } from 'uuid';

@Injectable()
export class TodosService {
  private todos: Todo[] = [];

  findAll(): Todo[] {
    return this.todos;
  }

  findOne(id: string): Todo {
    return this.todos.find(todo => todo.id === id);
  }

  create(createTodoDto: CreateTodoDto): Todo {
    const todo: Todo = {
      id: uuidv4(),
      isCompleted: false,
      ...createTodoDto
    };
    this.todos.push(todo);
    return todo;
  }

  update(id: string, updateTodoDto: CreateTodoDto): Todo {
    const todo = this.findOne(id);
    if (!todo) {
      return null;
    }
    this.todos = this.todos.map(t => t.id === id ? { ...t, ...updateTodoDto } : t);
    return this.findOne(id);
  }

  delete(id: string): boolean {
    const initialLength = this.todos.length;
    this.todos = this.todos.filter(todo => todo.id !== id);
    return this.todos.length < initiallyLength;
  }
}
```

#### Step 4: Implement the Controller

Controllers manage incoming HTTP requests:

```typescript
import { Controller, Get, Post, Put, Delete, Body, Param } from '@nestjs/common';
import { TodosService } from './todos.service';
import { Todo } from './todo.model';
import { CreateTodoDto } from './create-todo.dto';

@Controller('todos')
export class TodosController {
  constructor(private readonly todosService: TodosService) {}

  @Get()
  findAll(): Todo[] {
    return this.todosService.findAll();
  }

  @Post()
  create(@Body() createTodoDto: CreateTodoDto): Todo {
    return this.todosService.create(createTodoDto);
  }
}
```

### Adding Swagger Documentation

Swagger integration in NestJS is straightforward thanks to the `@nestjs/swagger` module:

**Install Swagger Module:**
```bash
npm install @nestjs/swagger swagger-ui-express
```

**Setup Swagger in your main application file (`main.ts`):**
```typescript
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module';
import { NestFactory } from '@nestjs/core';

async function bootstrap() {
    const app = await NestFactory.create(AppModule);
    const config = new DocumentBuilder()
    .setTitle('To-Do API')
    .setDescription('The To-Do API description')
    .setVersion('1.0')
    .build();
    const document = SwaggerModule.createDocument(app, config);
    SwaggerModule.setup('api', app, document);

    await app.listen(3000);
}
bootstrap();
```

### Running the Application

```bash
npm run start:dev
```

Visit `http://localhost:3000/api` to see your interactive Swagger API documentation, where you can also test your API endpoints.


### Adding Swagger annotations

#### Step 5: Add Swagger annotations to To-Do Model

Enhance your data model with Swagger annotations. Modify `todo.model.ts`:

```typescript
import { ApiProperty } from '@nestjs/swagger';

export class Todo {
    @ApiProperty({
        description: 'Unique identifier of the todo item',
        example: 'a1b2c3'
    })
    id: string;

    @ApiProperty({ description: 'Title of the todo item', example: 'Buy milk' })
    title: string;

    @ApiProperty({
        description: 'Detailed description of the todo item',
        example: 'Buy low-fat milk from the local store',
        required: false
    })
    description?: string;

    @ApiProperty({
        description: 'Indicates whether the todo item is completed',
        example: false
    })
    isCompleted: boolean;
}
```

#### Step 6: Add Swagger annotations to DTO

The `CreateTodoDto` also benefits from Swagger annotations, Modify `create-todo.dto.ts`:

```typescript
import { ApiProperty } from '@nestjs/swagger';

export class CreateTodoDto {
    @ApiProperty({ description: 'Title of the todo item', example: 'Buy milk' })
    title: string;

    @ApiProperty({
        description: 'Detailed description of the todo item',
        example: 'Buy low-fat milk from the local store',
        required: false
    })
    description?: string;
}

```

#### Step 7: Add Swagger annotations to Controller

Controllers `todos.controller.ts` now utilize Swagger to document the API routes:

```typescript
import {
    Controller,
    Get,
    Post,
    Put,
    Delete,
    Body,
    Param
} from '@nestjs/common';
import { TodosService } from './todos.service';
import { Todo } from './todo.model';
import { CreateTodoDto } from './create-todo.dto';
import { ApiTags, ApiBody, ApiResponse } from '@nestjs/swagger';

@Controller('todos')
export class TodosController {
    constructor(private readonly todosService: TodosService) {}

    @Get()
    @ApiResponse({ status: 200, description: 'Get all todos', type: [Todo] })
    findAll(): Todo[] {
        return this.todosService.findAll();
    }

    @Get(':id')
    @ApiResponse({ status: 200, description: 'Get a todo', type: Todo })
    findOne(@Param('id') id: string): Todo {
        return this.todosService.findOne(id);
    }

    @Post()
    @ApiBody({ type: CreateTodoDto })
    @ApiResponse({ status: 201, description: 'Create a new todo', type: Todo })
    create(@Body() createTodoDto: CreateTodoDto): Todo {
        return this.todosService.create(createTodoDto);
    }

    @Put(':id')
    update(
        @Param('id') id: string,
        @Body() updateTodoDto: CreateTodoDto
    ): Todo {
        return this.todosService.update(id, updateTodoDto);
    }

    @Delete(':id')
    delete(@Param('id') id: string): boolean {
        return this.todosService.delete(id);
    }
}
```

### Running the Application Again (If stopped)

```bash
npm run start:dev
```

Visit `http://localhost:3000/api` to see your interactive Swagger API documentation with models descriptions.

Happy Coding 🚀


---

### Quick notes on Swagger

**Swagger** is often mentioned alongside the **OpenAPI Specification**, but it's important to understand the distinction and connection between them. **Swagger**, initially a combination of tools for designing and documenting RESTful APIs, has evolved to be closely associated with the OpenAPI Specification.


| **Category** | **Description**  |
|--------------|------------------|
| **Swagger Tools** | Originally, Swagger included tools like Swagger UI, Swagger Editor, and Swagger Codegen for designing, documenting, and consuming RESTful APIs. |
| **OpenAPI Specification** | Initially known as the Swagger Specification, it's a standard format for describing RESTful APIs, facilitating standardized API interactions. |
| **Relationship** | In 2015, Swagger Specification was donated by SmartBear Software to the OpenAPI Initiative and renamed the OpenAPI Specification, while Swagger tools continued to support it. |
| **Usage** | Today, "Swagger" often refers to the suite of tools supporting the OpenAPI Specification, allowing developers to visualize and interact with APIs without direct access to their implementation. |

🔥 Hit 'Fire' if you enjoyed this!