๐ Setup
npm i @nestjs/cli
- Install the Nest.js CLI library.nest new [project-name]
- Create a new project.- If the folder is already created, use
nest new ./
instead.
- If the folder is already created, use
The generated directory and files will look like this:
โโโ README.md
โโโ nest-cli.json
โโโ node_modules
โโโ package-lock.json
โโโ package.json
โโโ .gitignore
โโโ .eslintrc.js
โโโ .prettierrc
โโโ src
โ โโโ app.controller.spec.ts
โ โโโ app.controller.ts
โ โโโ app.module.ts
โ โโโ app.service.ts
โ โโโ main.ts
โโโ test
โ โโโ app.e2e-spec.ts
โ โโโ jest-e2e.json
โโโ tsconfig.build.json
โโโ tsconfig.json
๐ Controller
A controller is responsible for handling incoming requests from clients and returning responses.
In Nest.js, controllers handle routing using decorators such as
@Post
,@Get
,@Put
,@Patch
,@Delete
.You can generate files and test files for a controller using
nest g controller [name]
.
๐ Provider
A provider is a fundamental concept in Nest that includes services, repositories, factories, helpers, and more. Providers are objects that can be injected as dependencies. In other words, they are objects that have associations with other systems.
Service
The service layer contains business logic.
You can generate files and test files for a service using
nest g service [name]
.
Repository
The repository layer contains methods for executing database queries.
Create repository files manually.
If you are using MongoDB, you can refer to this blog post for repository usage.
Note about TypeORM: In previous versions, the
@EntityRepository
decorator was used, but it has been deprecated. Instead, you need to inherit theRepository
class provided by TypeORM. You can find the usage in this blog post (assuming we are using MySQL and focusing on TypeORM).
๐ Module
Modules are used by Nest to manage the application structure by providing metadata. Each application has one or more root modules, which define the relationships and dependencies between modules and providers.
You can generate module files using
npm g module [name]
.For TypeORM, you need to modify the module.ts files of each module as follows:
@Module({
imports: [TypeOrmModule.forFeature([EntityName])],
controllers: [SomethingController],
providers: [SomethingService, SomethingRepository],
})
export class HospitalsModule {}
Add
TypeOrmModule.forFeature([EntityName])
to theimports
array.Add repositories to the
providers
array.
๐ main.ts File
const logger = new Logger();
const app = await NestFactory.create(AppModule);
// Global validation pipe
app.useGlobalPipes(
new ValidationPipe({
whitelist: true, // Automatically remove properties that do not exist in the payload and DTO class
forbidNonWhitelisted: true, // Throw an exception instead of removing disallowed properties
transform: true, // Automatically transform the payload received over the network into the designated object based on the DTO class
}),
);
// Global HTTP exception filter
app.useGlobalFilters(new HttpExceptionFilter()); // Global filter
// CORS
app.enableCors();
// Config
const config = app.get<ConfigType<typeof appConfig>>(appConfig.KEY);
const port = config.port;
await app.listen(port);
if (config.mode === 'development') logger.log(`Server is running on port ${port}`);
Basic CORS settings are added.
The global validation pipe (validation & transformation) is defined. (Requires installation of the following libraries:
npm i --save class-validator class-transformer
)
๐ Config Environment Variable Management
Install the following packages:
npm i --save @nestjs/config cross-env joi
.You can access environment variables using the
ConfigService
andConfigType
provided by theConfigModule
. UsingConfigType
allows you to read environment variables in a more type-safe manner and makes it easier to manage environment variables by separating them by functionality.Reference site: https://www.daleseo.com/nestjs-configuration/
๐ HTTP Request Logger Middleware Configuration
- In
app.module.ts
, configure the middleware as follows. It will log requests only in development mode.
export class AppModule implements NestModule {
private readonly isDev: boolean = process.env.MODE === 'development' ? true : false;
// Log HTTP requests in dev mode
configure(consumer: MiddlewareConsumer) {
if (this.isDev) {
consumer.apply(HTTPLoggerMiddleware).forRoutes('*');
}
}
}
- Here's an example of
HTTP-logger.middleware.ts
:
@Injectable()
export class HTTPLoggerMiddleware implements NestMiddleware {
private logger = new Logger('HTTP'); // Logger for HTTP protocol
use(req: Request, res: Response, next: NextFunction) {
// Log when the response is finished (finish event)
res.on('finish', () => {
this.logger.log(`${req.ip} ${req.method}, ${res.statusCode}`, req.originalUrl);
});
next();
}
}
๐ HTTP Exception Filter
Nest.js provides built-in exception filtering for handling HTTP responses. For example, if a server error occurs, Nest will throw an error response like this:
{
"statusCode": 500,
"message": "Internal server error"
}
You can use an exception filter to handle such error responses that are thrown either by Nest.js itself or by using throw new HttpException()
to customize the response.
import { Catch, HttpException } from '@nestjs/common';
@Catch(HttpException)
export class HttpExceptionFilter {
catch(exception, host) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
const status = exception.getStatus();
const error = exception.getResponse() as string | { error: string; statusCode: number; message: string | string[] };
// Handling error thrown using `throw new HttpException()`
if (typeof error === 'string') {
response.status(status).json({
success: false,
error,
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
});
}
// Handling error responses handled by Nest itself
else {
response.status(status).json({
success: false,
...error,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
}