Minimal NestJS setup for API project

Table of contents

When starting new enterprise-level NestJS-based project it is fat not enough to run $ nest new command to cover minimal infra requirements. Usually initial framework setup misses next things for such project:

To cover these requirements usually it is required to pull a bunch of additional packages such as typeorm, passport, class-validator, cache-manager, etc.

I've created a repo with working example of NestJS application covering all the items above, take a look - nestjs-starter-kit.

Let's go over these requirements and see how they are solved in nestjs-starter-kit.

Docker setup

For this example we will require only Node.js running on local machine, all other instances will be run in Docker: Postgres DB, Redis for cache and Mailhog for mail-trapping.

Example of docker-compose.yml

Env file setup

According to 12 factor app - it is recommended to store application config in Environment Variables. This technique allows you to build the bundle once and deploy it to multiple target servers (e.g. QA, Staging, Prod) without code modifications. Each target environment will have different configuration values which application retrieves from environment variables.

NestJS does not provide .env file support right after installation - it is required to add more configs manually.

This requirement covered in app.module.ts and configuration.ts files.

Validation vie DTO files

NestJS does not provide validation functionality right after installation - it is required to configure Validation pipeline.

DB migrations

TypeORM DB migrations are already set up for you in ./api/src/db/migrations folder.

To generate new migration run:

npm run migrations:new -- src/db/migrations/Roles

To apply migrations run:

npm run migrations:up

To revert migrations run:

npm run migrations:revert

Redis cache

cache-manager package with Redis store is available in app-cache.module.ts file.

So it is possible to use CacheInterceptor above your controller methods or classes:

  @UseInterceptors(CacheInterceptor)
  @Get()
  async getUsers() {}

Or inject CacheManager and use it directly:

constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

await this.cacheManager.get('key');

JWT auth with passport.js

JWT authentication is configured and available to use.

User registration, login and JWT-protected API examples were added in user.controller.ts.

Logger with Trace ID generation

Pino added as application logger to utilize async way of logging without blocking main thread.

Each request to API is signed with unique TraceID and passed to logger via AsyncLocalStorage.

Code can be found in async-storage.middleware.ts and app-logger.service.ts.

TraceID in logs example

Graceful shutdown

NestJS shutdown hooks are enabled.

This starter kit subscribed to OnModuleDestroy event and disconnects from Redis gracefully.

Automatic APIs documentation with Swagger

NestJS swagger module configured with the use of Swagger CLI plugin.

API docs are generated with the start of app server automatically and available at http://localhost:3000/api:

Swagger doc generated

Summary

This post described what is missing in default NestJS installation for enterprise-level API projects, reviewed nestjs-starter-kit project and showed how this project could help you in quick bootstrapping NestJS APIs.