I'm currently learning Nest.JS framework and because I organized my notes very well I decided to share them in this NestJS tutorial post.
I'm planning to make a boilerplate app with throughout this Nest.JS tutorial. The app will cover a simple authentication.
In this part, I'm going to try to explain basics of Nest and its basic concepts.
Since understanding NestJS requires some software development concepts, I will try to explain those concepts also:
- Dependency Inversion Principle
- Dependency Injection
- Inversion of Control
For the demonstration purposes, let's look some basics of NestJS. You don't need to do anything rightnow until the next sextion. (We are going to create a Nest.js project with the CLI in the next section)
A) TypeScript Configurations in NestJS
B) NestJS Components
|Pipe||Data validation in requests|
|Modules||Groups the code together. A module wraps the controller.|
|Controller||Route the request to a specific function|
|Filters||Handles errors that occur during request handling|
|Interceptors||Adds extra logic to incoming requests or outcoming responses|
C) Creating a project with the CLI
Another way of starting a NestJS project is scaffolidng with the Nest CLI.
You can visit
http://localhost:3000 on your browser. You'll see that our app is running.
D) Creating a project manually
When you create a new project from scratch you need to install the libraries below.
Let's look what are those for:
|@nestjs/common||The functions, classes and other useful stuff except the core package.|
|@nestjs/core||The core package of NestJS.|
|@nestjs/platform-express||Express library for handling HTTP requests. You can also choose Fastify as well.|
|reflect-metadata||It is for using decorators.|
E) The Basic App Structure
After installation, we will see the default file structure and simple explanations taken from the official document.
|app.controller.ts||A basic controller with a single route.|
|app.controller.spec.ts||The unit tests for the controller.|
|app.module.ts||The root module of the application.|
|app.service.ts||A basic service with a single method.|
|main.ts||The entry file of the application which uses the core function NestFactory to create a Nest application instance.|
1) NestJS Tutorial
Nest aims to be a platform-agnostic framework. It works with any NodeJS server. However, out-of-the-box, it supports Express and Fastify.
Those platform-specific configurations and the most general NestJS configurations can be done with the app's entry point.
main.ts file which is the entry point of the app.
A Nest application can be created with the
create method which returns an app object that fulfills the INestApplication interface.
Later on, we will use some of the methods of the returned app object such as
By default, NestJS uses Express as its default Node server. You can use Fastify with NestJS as well as other Node servers.
2) Modules in NestJS
In Nest.js, every app has at least one module. Modules encapsulate closely related code components together. It is strongly suggested to use modules for organizing your code. By doing that, you can easily scale your code.
A module is a class annotated with a
@Module() decorator. In other words, we use
@Module() decorator with an object, in order to make a class a module.
A) The Root module
When you create a Nest app with the CLI, the root module of your app will be in
B) What is a decorator?
Decorator is a concept that related with Decorator pattern which is a design pattern in object-oriented programming.
Decorators are functions that let you attach new behaviors to objects by placing these objects inside a special wrapper.
- Property Decorators
- Method Decorators
- Accessor Decorators
- Parameter Decorators and
- Class Decorators, like we use in modules.
A class decorator is applied to the constructor of a class. It can observe, modify or replace a class definition. Also, it should be noted that a class decorator can not be used in a TypeScript declaration file.
For the details, you can check Decorators in TypeScript
You can also read this excellent article: A complete guide to TypeScript Decorators
Let's back to the modules.
C) Properties of the Module object
I said that a module decorator takes a single object. The properties of the object describe the module.
|providers||the providers that will be instantiated by the Nest injector and that may be shared at least across this module|
|controllers||the set of controllers defined in this module which have to be instantiated|
|imports||the list of imported modules that export the providers which are required in this module|
|exports||the subset of providers that are provided by this module and should be available in other modules which import this module. You can use either the provider itself or just its token (provide value)|
D) Notes on Modules
Some important things about the modules in NestJS:
- Modules use singleton design pattern. Therefore we can share the instance of any service provider between modules.
- Every module is automatically a shared module. Once created it can be reused by any module.
- We need to import its module first when we need to use any provider.
- Any module imported to another module also can be exported from.
- Because providers aren't registered in global scope, importing a specific module many times can be tedious. You can go around this problem by adding
@Globaldecorator to a module (except lazy-loaded modules).
E) Create a new module with the CLI
Let's create a new module that will be responsible for the users of our app. If your Nest.JS app is running, you can stop it by pressing
CMD/CTRL + C.
In your terminal, execute the commands below:
This will create
users folder under
src directory. Under this directory, you'll see
The module file is empty now. Let's fill it with some code components.
3) Controllers in NestJS
I previously said that a controller is responsible for routing a request to a specific function. Controllers are connected our app through a module.
There is a better way to create controller and resources than what we will do. Since this is a tutorial about NestJS, I am going to do many tasks manually. Otherwise, you can quickly create a CRUD API.
A) Creating a controller
Let's create a controller.
When you execute the command above, two new files will be generated:
users.controller.spec.ts. The latter one is for test purposes and thus we can skip it now.
B) Notes on controllers
Also, please check the
users.module.ts file. You can see that the new controller is automatically appended to its module.
There are some things to be highlighted:
- Don't add contoller suffix to your controller name. It will be automatically suffixed.
- Putting --flat flag generates the controller without creating an extra folder. If you need more organized directory which put controller in a folder, you can omit it.
- The controller is automatically appended to the module
- The text in the controller decorator, which is "users" in our case, prefixes the routes under the controller. In other words, all the routes under this controller will start with
C) Adding routes to the controller
We created a very basic controller.
We need to add routes with the corresponding HTTP request. We should specify HTTP requests with decorators.
Let's create a CRUD API.
D) REST API Client
To check our routes, there are several ways. You can use your favorite REST API Client such as Postman, Insomnia, Paw. I'm planning to use Thunder Client throughout this post. It is an extension for VS Code. If you are a VS Coder, the chances are high that you like it.
For the detailed instructions, you can visit: NestJS Controllers - Routing.
Since a controller method will be responsible only for routing, we need to create a service that will handle the business logic of our app.
E) Request, Response, Status, Body, Query, and Parameters
To get HTTP request and response objects and their properties like body, query, parameters, you can use their decorators:
You should also import underlying server type library if you need to take the advantage. (See the details)
|@Param(key?: string)||req.params / req.params[key]|
|@Body(key?: string)||req.body / req.body[key]|
|@Query(key?: string)||req.query / req.query[key]|
|@Headers(name?: string)||req.headers / req.headers[name]|
There are also other method decorators for your usage.
|@HttpCode(statusCode: number)||Returns HTTP status code you given|
|@Redirect(url?: string, statusCode?: number)||Redirect a response to a given URL with a given HTTP code|
Dynamic Routes and Query Variables
In some cases, we will require dynamic routes, for instance, the
getUser route. You can obtain a dynamic
id value with a special parameter decorator
@Param(). You can optionally pass the dynamic parameter name to get its dynamic value; otherwise, you will get an object.
It should be noted that if you don't decorate the method with a dynamic route (with a colon and a parameter name) like
:id you can't obtain the value.
The same workflow is also valid for query strings in your route, except we use the
Let's change your controller's
getUser method by first importing
Query decorators from
After import, I'll assign route parameter to
params and query string to
qs by decorating them.
For demonstration purposes, I can send a get request to the route:
You'll see the logs below on your termina:
It is better to demonstrate a PUT request. In order to that, send a PUT request to
http://localhost:3000/users with the JSON payload
Headers decorator from
@nestjs/common and change
Since a controller method will be responsible only for routing, we need to create a service that will handle the business logic of our app. However, are we sure about the validity of requested data? Let's be sure about that.
4) Pipes (Data Validation )
Pipes in NestJS are for data validation in requests. They validate or transform the data before reaching the controller.
The two usecase of pipes are below.
- Data validation
- Data transformation
To use those functionalities, we need to install two extra packages in the next step. Those are:
- class-transformer: Decorator-based transformation, serialization, and deserialization between objects and classes.
- class-validator: Decorator-based property validation for classes.
NestJS provides eight pipes available out-of-the-box, you could also write your own. Those built-in pipes are:
DefaultValuePipe. You can read the details: NestJS Pipe
Now, there are a couple of things to do for setting automatic validation.
- We will register the validation globally;
- We should define the expected data, which we will call "data transfer object."
- We should define validation rules and apply all of them to a request handler.
A) Registering a Global Pipe
To use the ValidationPipe, we need to tell NestJS to use this validation globally. In other words, we need to set up automatic validation globally. After registering the ValidationPipe globally, we will define different rules for different routes.
Open and edit the
main.ts file accordingly.
B) Data Transfer Object - dto
The next step is creating a class that describes the rules the request body must-have. This class is referred to as
Data Transfer Object, generally abbreviated as
We will create a file that includes a class that describes all the different properties we expect our post request handler to receive.
We've created three different dto files. Now, we will define those files and ensure the requested data is valid.
We decorate dto objects with the decorators imported from
The validation classes are ready. When we put those as a type annotation of any request, they will validate incoming requests.
Let's try them. You can update
users.controller.ts file according to this:
It is time to test it. I am going to send a post request to
createUser route with a missing
The result will be as expected.
I think this is enough for the first post of Nest.JS tutorial. I'm planning to cover providers and interceptors in the next post. Thanks for reading.