Lesson 1
Set Up GET Queries - Get All and Get By ID
Introduction and Context Setting

Welcome to the first lesson of our course on "Building a To-Do REST API with NestJS". In this course, we'll learn how to create a To-Do application using NestJS. A REST API (Representational State Transfer Application Programming Interface) is a way for different software systems to communicate over the internet. NestJS is a framework for building efficient, reliable, and scalable server-side applications with REST at the core.

NestJS provides built-in support for complete application development, making it a versatile choice for building APIs. It is built on top of Express.js but adds many valuable features and an Angular-inspired structure to make development easier.


Setting Up the Project Environment

Before we dive into the code, let's set up our project environment. Although the CodeSignal environment comes pre-installed with necessary libraries, it's essential to know how to set things up locally.

  1. Installing NestJS Locally:

    • First, you need Node.js installed on your system. You can download it from Node.js.
    • Install the Nest CLI globally using npm:
      Bash
      1npm install -g @nestjs/cli
    • Create a new project using the Nest CLI:
      Bash
      1nest new todo-app
  2. Project Structure:

    • The basic file structure includes:
      • src/ folder: Contains the main application files.
      • main.ts: The entry file for the application.
      • app.module.ts: The root module of the application.

For our example, we'll assume the environment is already set up on CodeSignal.


Creating the TodoController

Controllers in NestJS handle incoming requests and return responses to the client. Let's create our TodoController. In a REST API, you will want to map web requets with different verbs. The most common verb is GET which indicates that you are querying data, not modifying it. It is very common in a REST API to include two GET handlers for a Resource. In this case, our Resource is Todo and our GET queries handle getting all Todos in addition to getting a single Todo by ID.

Step-by-Step Code
TypeScript
1import { Controller, Get, Param } from '@nestjs/common'; 2import { TodoService } from './todo.service'; 3import { TodoDto } from './dto/todo.dto'; 4 5@Controller('todos') // Define the controller to handle all /todos routes 6export class TodoController { 7 constructor(private readonly todoService: TodoService) {} // Inject the TodoServices 8 9 @Get() // Handle the GET request for getting all Todos via /todos 10 findAll(): TodoDto[] { 11 return this.todoService.findAll(); 12 } 13 14 @Get(':id') // Extend the /todos route to GET a single Todo via the /todos/:id route 15 findOne( 16 // Use the @Param('id') decorator to decoare that the :id in the route will map to the id parameter 17 @Param('id') id: string, 18 ): TodoDto { 19 return this.todoService.findOne(id); 20 } 21}

Creating the TodoService

Services in NestJS contain the business logic of the application. Let's set up our TodoService.

Step-by-Step Code
TypeScript
1import { Injectable } from '@nestjs/common'; 2import { TodoDto } from './dto/todo.dto'; 3 4@Injectable() // Declare the TodoService to be available as an injectable service via Dependency Injection 5export class TodoService { 6 7 // For now, let's populate this service with some data 8 private todos: TodoDto[] = [ 9 { 10 id: '1', 11 title: 'Learn NestJS', 12 description: 'Learn how to build with NestJS', 13 completed: true, 14 }, 15 { 16 id: '2', 17 title: 'Learn REST', 18 description: 'Learn how to build interactive REST APIs', 19 completed: false, 20 }, 21 ]; 22 23 // fetch all of the Todo items. 24 findAll(showIncomplete?: boolean): TodoDto[] { 25 return this.todos; 26 } 27 28 // fetch only one item and return null if it does not exist. 29 findOne(id: string): TodoDto | null { 30 return this.todos.find(todo => todo.id === id) || null; 31 } 32}

This service mimics interaction with a database through an in-memory array.


Connecting the Controller and Service

Now that we have both the controller and the service, it's time to connect them.

Step-by-Step Explanation
  • In TodoController, we inject TodoService through the constructor using Dependency Injection.
  • In the findAll method of TodoController, we call this.todoService.findAll() to fetch all To-Dos.
  • In the findOne method of TodoController, we call this.todoService.findOne(id) to fetch a specific To-Do by ID.

Summary and Next Steps

In this lesson, we covered the basics of setting up GET queries in a NestJS application. We learned how to create a simple TodoController and TodoService, connect them, and test our GET endpoints to fetch all To-Dos and fetch a specific To-Do by ID.

Next, you will get hands-on practice with these concepts. Try modifying the code, adding new routes, or changing the mock data to better understand how everything works together.

Great job on completing this lesson! Keep up the good work, and let's move on to the practice exercises to solidify your understanding.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.