
First Steps Nest Js
Table of Contents
First Steps
Prerequisites
Please make sure that Node.js (version >= 16) is installed on your operating system.
Here’s a brief overview of those core files:
file name | description |
---|---|
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. |
There are two HTTP platforms supported out-of-the-box: express and fastify. You can choose the one that best suits your needs.
- platform-express - Express is a well-known minimalist web framework for node. It’s a battle tested, production-ready library with lots of resources implemented by the community. The @nestjs/platform-express package is used by default. Many users are well served with Express, and need take no action to enable it.
- platform-fastify - Fastify is a high performance and low overhead framework highly focused on providing maximum efficiency and speed.
Info: To speed up the development process (x20 times faster builds), you can use the SWC builder by passing the -b swc flag to the start script, as follows npm run start – -b swc. More here.
Controllers
Controllers are responsible for handling incoming requests and returning responses to the client.
Info: For quickly creating a CRUD controller with the validation built-in, you may use the CLI’s CRUD generator: nest g resource [name].
CRUD generator seems a cool CLI tool!!
$ nest g resource
? What name would you like to use for this resource (plural, e.g., "users")? users
? What transport layer do you use? REST API
? Would you like to generate CRUD entry points? Yes
CREATE src/users/users.controller.spec.ts (566 bytes)
CREATE src/users/users.controller.ts (894 bytes)
CREATE src/users/users.module.ts (248 bytes)
CREATE src/users/users.service.spec.ts (453 bytes)
CREATE src/users/users.service.ts (609 bytes)
CREATE src/users/dto/create-user.dto.ts (30 bytes)
CREATE src/users/dto/update-user.dto.ts (169 bytes)
CREATE src/users/entities/user.entity.ts (21 bytes)
UPDATE package.json (1980 bytes)
UPDATE src/app.module.ts (312 bytes)
✔ Packages installed successfully.
Created these many files.
To create a controller
$ nest g controller [name]
This will create a dir inside src/
with cat.controller.ts
and cats.controller.spec.ts
on it.
Updates the app.module.ts
file with new controllers inside the array.
Angular vibe!;)
Providers
Controllers should handle HTTP requests and delegate more complex tasks to providers.
Providers are plain JavaScript classes that are declared as providers in a module.
Info: To create a service using the CLI, simply execute the $ nest g service cats command.
Providers are injected into Controllers. This is done via Constructor inside Controller.
Provider registration
Now that we have defined a provider (CatsService),
and we have a consumer of that service (CatsController),
we need to register the service with Nest so that it can perform the injection.
We do this by editing our module file (app.module.ts) and adding the service to the providers array of the @Module() decorator.
Modules
A module is a class annotated with a @Module() decorator.
The @Module() decorator provides metadata that Nest makes use of to organize the application structure.
Each application has at least one module, a root module.
The module encapsulates providers by default.
The CatsController and CatsService belong to the same application domain. As they are closely related, it makes sense to move them into a feature module. A feature module simply organizes code relevant for a specific feature, keeping code organized and establishing clear boundaries. This helps us manage complexity and develop with SOLID principles, especially as the size of the application and/or team grows.
Info: To create a module using the CLI, simply execute the $ nest g module cats command.
Middleware
Middleware is a function which is called before the route handler. Middleware functions have access to the request and response objects, and the next() middleware function in the application’s request-response cycle. The next middleware function is commonly denoted by a variable named next.
Exception filters
Nest comes with a built-in exceptions layer which is responsible for processing all unhandled exceptions across an application. When an exception is not handled by your application code, it is caught by this layer, which then automatically sends an appropriate user-friendly response.
The one which provides this response!
{
"statusCode": 500,
"message": "Internal server error"
}
Pipes
Pipes have two typical use cases:
transformation: transform input data to the desired form (e.g., from string to integer)
validation: evaluate input data and if valid, simply pass it through unchanged; otherwise, throw an exception
Nest comes with nine pipes available out-of-the-box:
- ValidationPipe
- ParseIntPipe
- ParseFloatPipe
- ParseBoolPipe
- ParseArrayPipe
- ParseUUIDPipe
- ParseEnumPipe
- DefaultValuePipe
- ParseFilePipe
Object schema validation pipes
We can use zod for this!
@Post()
@UsePipes(new ZodValidationPipe(createCatSchema))
create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
Inside a controller.
Gaurds
A guard is a class annotated with the @Injectable() decorator, which implements the CanActivate interface.
Guards have a single responsibility. They determine whether a given request will be handled by the route handler or not, depending on certain conditions (like permissions, roles, ACLs, etc.) present at run-time.
ACL??
This is often referred to as authorization. Authorization and its cousin, authentication.
Guards are executed after all middleware, but before any interceptor or pipe.
Interceptors
Interceptors have a set of useful capabilities which are inspired by the Aspect Oriented Programming (AOP) technique. They make it possible to:
- bind extra logic before / after method execution
- transform the result returned from a function
- transform the exception thrown from a function
- extend the basic function behavior
- completely override a function depending on specific conditions (e.g., for caching purposes)
Testing
We do check that we have things correctly right? and while building a huge project we have to check the current progress and the previous outputs too. Being a human we can miss out on somethings which will bug us later on. I feel it essential to write tests for modules that are completed and checked. That way our development time will be reduced and we can focus on working ahead.
NestJS uses Jest for testing.