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.
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.
-
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
:Bash1npm install -g @nestjs/cli
- Create a new project using the Nest CLI:
Bash
1nest new todo-app
- First, you need
-
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.
- The basic file structure includes:
For our example, we'll assume the environment is already set up on CodeSignal.
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 Todo
s in addition to getting a single Todo
by ID.
TypeScript1import { 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}
Services in NestJS contain the business logic of the application. Let's set up our TodoService
.
TypeScript1import { 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.
Now that we have both the controller and the service, it's time to connect them.
- In
TodoController
, we injectTodoService
through the constructor using Dependency Injection. - In the
findAll
method ofTodoController
, we callthis.todoService.findAll()
to fetch all To-Dos. - In the
findOne
method ofTodoController
, we callthis.todoService.findOne(id)
to fetch a specific To-Do by ID.
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.