NestJS Day 1: Basic Walkthrough
Abstract
This is a concise, summarized approach to learn NestJS. For more in-depth knowledge about NestJS, visit the official NestJS documentation.
Nest CLI
Before creating a new NestJS project, you need to install the NestJS CLI globally. You can do this by running the following command:
npm install -g @nestjs/cli
To see a list of available commands, run the following command:
nest --help
Output:
Usage: nest <command> [options]
Options: -v, --version Output the current version. -h, --help Output usage information.
Commands: new|n [options] [name] Generate Nest application. build [options] [app] Build Nest application. start [options] [app] Run Nest application. info|i Display Nest project details. add [options] <library> Adds support for an external library to your project. generate|g [options] <schematic> [name] [path] Generate a Nest element. Schematics available on @nestjs/schematics collection: ┌───────────────┬─────────────┬──────────────────────────────────────────────┐ │ name │ alias │ description │ │ application │ application │ Generate a new application workspace │ │ class │ cl │ Generate a new class │ │ configuration │ config │ Generate a CLI configuration file │ │ controller │ co │ Generate a controller declaration │ │ decorator │ d │ Generate a custom decorator │ │ filter │ f │ Generate a filter declaration │ │ gateway │ ga │ Generate a gateway declaration │ │ guard │ gu │ Generate a guard declaration │ │ interceptor │ itc │ Generate an interceptor declaration │ │ interface │ itf │ Generate an interface │ │ middleware │ mi │ Generate a middleware declaration │ │ module │ mo │ Generate a module declaration │ │ pipe │ pi │ Generate a pipe declaration │ │ provider │ pr │ Generate a provider declaration │ │ resolver │ r │ Generate a GraphQL resolver declaration │ │ service │ s │ Generate a service declaration │ │ library │ lib │ Generate a new library within a monorepo │ │ sub-app │ app │ Generate a new application within a monorepo │ │ resource │ res │ Generate a new CRUD resource │ └───────────────┴─────────────┴──────────────────────────────────────────────┘
To know more about a specific command, run the following command:
nest <command> --help
Example, nest generate --help
.
Output:
Usage: nest generate|g [options] <schematic> [name] [path]
Generate a Nest element. Schematics available on @nestjs/schematics collection: ┌───────────────┬─────────────┬──────────────────────────────────────────────┐ │ name │ alias │ description │ │ application │ application │ Generate a new application workspace │ │ class │ cl │ Generate a new class │ │ configuration │ config │ Generate a CLI configuration file │ │ controller │ co │ Generate a controller declaration │ │ decorator │ d │ Generate a custom decorator │ │ filter │ f │ Generate a filter declaration │ │ gateway │ ga │ Generate a gateway declaration │ │ guard │ gu │ Generate a guard declaration │ │ interceptor │ itc │ Generate an interceptor declaration │ │ interface │ itf │ Generate an interface │ │ middleware │ mi │ Generate a middleware declaration │ │ module │ mo │ Generate a module declaration │ │ pipe │ pi │ Generate a pipe declaration │ │ provider │ pr │ Generate a provider declaration │ │ resolver │ r │ Generate a GraphQL resolver declaration │ │ service │ s │ Generate a service declaration │ │ library │ lib │ Generate a new library within a monorepo │ │ sub-app │ app │ Generate a new application within a monorepo │ │ resource │ res │ Generate a new CRUD resource │ └───────────────┴─────────────┴──────────────────────────────────────────────┘
Options: -d, --dry-run Report actions that would be taken without writing out results. -p, --project [project] Project in which to generate files. --flat Enforce flat structure of generated element. --no-flat Enforce that directories are generated. --spec Enforce spec files generation. (default: true) --skip-import Skip importing (default: false) --no-spec Disable spec files generation. -c, --collection [collectionName] Schematics collection to use. -h, --help Output usage information.
To Learn more about CLI, visit official CLI doc.
Create & Running a Project
Run the following command to create a project,
nest new <project-name>
Then select a package manager, I am going to select pnpm
. I’ve ran nest new shamscorner-nestjs
command. My project name is shamscorner-nestjs
. If you run the exact command, you should see the following output:
⚡ We will scaffold your app in a few seconds..
? Which package manager would you ❤️ to use? pnpmCREATE shamscorner-nestjs/.eslintrc.js (663 bytes)CREATE shamscorner-nestjs/.prettierrc (51 bytes)CREATE shamscorner-nestjs/README.md (3347 bytes)CREATE shamscorner-nestjs/nest-cli.json (171 bytes)CREATE shamscorner-nestjs/package.json (1949 bytes)CREATE shamscorner-nestjs/tsconfig.build.json (97 bytes)CREATE shamscorner-nestjs/tsconfig.json (546 bytes)CREATE shamscorner-nestjs/src/app.controller.spec.ts (617 bytes)CREATE shamscorner-nestjs/src/app.controller.ts (274 bytes)CREATE shamscorner-nestjs/src/app.module.ts (249 bytes)CREATE shamscorner-nestjs/src/app.service.ts (142 bytes)CREATE shamscorner-nestjs/src/main.ts (208 bytes)CREATE shamscorner-nestjs/test/app.e2e-spec.ts (630 bytes)CREATE shamscorner-nestjs/test/jest-e2e.json (183 bytes)
✔ Installation in progress... ☕
🚀 Successfully created project shamscorner-nestjs👉 Get started with the following commands:
$ cd shamscorner-nestjs$ pnpm run start
Thanks for installing Nest 🙏 Please consider donating to our open collective to help us maintain this package.
🍷 Donate: https://opencollective.com/nest
Now, let’s navigate to the project directory and run the project.
cd shamscorner-nestjspnpm run start
If I open http://localhost:3000, I should see the hello world text. Awesome!
Language & Support
- Both TypeScript and JavaScript are supported in NestJS.
- TypeScript is the recommended language for NestJS.
- Node.js (version >= 20)
- Nest is platform agnostic
- Platforms supported out-of-the-box: Express and Fastify
Project overview
Markdown table
File | Description |
---|---|
src/app.controller.ts | A basic controller that returns a hello world message. |
src/app.controller.spec.ts | A test file for the app controller. |
src/app.module.ts | The root module of the application. |
src/app.service.ts | A basic service that returns a hello world message. |
src/main.ts | The entry file of the application. |
Let’s breakdown each file and understand what it does.
The src/main.ts
file is the entry point of the application. It creates a new NestJS application instance and starts the HTTP server on port 3000.
import { NestFactory } from "@nestjs/core";// Import the root AppModule that defines the application structure and componentsimport { AppModule } from "./app.module";
// Define an asynchronous bootstrap function to initialize the applicationasync function bootstrap() { // Create a new NestJS application instance with AppModule as the root module const app = await NestFactory.create(AppModule); // Start the HTTP server on port 3000 await app.listen(3000);}// Execute the bootstrap function to start the applicationbootstrap();
The src/app.module.ts
file is the root module of the application. It defines the application structure by importing and declaring other modules, controllers, and services.
import { Module } from "@nestjs/common";// Import the AppController which handles incoming requestsimport { AppController } from "./app.controller";// Import the AppService which contains the business logicimport { AppService } from "./app.service";
// @Module decorator to define this class as a NestJS module@Module({ imports: [], // List of imported modules that export providers needed in this module controllers: [AppController], // List of controllers defined in this module providers: [AppService], // List of providers (services) that can be injected in this module})export class AppModule {} // Export the AppModule class to be used in the bootstrap file
The src/app.service.ts
file is a basic service that returns a hello world message and responsible for the business logic.
import { Injectable } from "@nestjs/common";
// @Injectable decorator indicates this class can be managed by NestJS dependency injection system@Injectable()export class AppService { // Method that returns a simple string greeting // The ': string' indicates this function returns a string value getHello(): string { // Return a "Hello World!" message when this method is called return "Hello World!"; }}
The src/app.controller.ts
file is a basic controller that returns a hello world message. It delegates the business logic to the AppService
.
import { Controller, Get } from "@nestjs/common";
// Import the AppService from a local file// This service will contain the business logicimport { AppService } from "./app.service";
// @Controller() decorator marks this class as a NestJS controller// Empty parentheses mean this controller handles requests to the root route '/'// You could specify a path like @Controller('users') to handle '/users' routes@Controller()export class AppController { // Constructor with dependency injection // 'private readonly' makes appService a private, immutable property of the class // NestJS will automatically inject an instance of AppService here constructor(private readonly appService: AppService) {}
// @Get() decorator marks this method as a handler for GET requests // Empty parentheses mean it handles the root path of this controller // Combined with the controller's path, this handles GET requests to '/' @Get() // Method declaration with TypeScript return type annotation (string) // This method will be called when a GET request is made to the root route getHello(): string { // The controller delegates the business logic to the service // This maintains separation of concerns - controllers handle HTTP, // while services handle business logic return this.appService.getHello(); }}
Finally, the src/app.controller.spec.ts
file is a test file for the AppController
. It uses Jest to test the controller’s behavior.
import { Test, TestingModule } from "@nestjs/testing";import { AppController } from "./app.controller";import { AppService } from "./app.service";
// Main test suite for AppControllerdescribe("AppController", () => { // Declare a variable to hold the controller instance let appController: AppController;
// Before each test, set up a testing module beforeEach(async () => { // Create a testing module that mimics the actual application module const app: TestingModule = await Test.createTestingModule({ controllers: [AppController], // Register the controller to test providers: [AppService], // Register the service dependencies }).compile(); // Compile the module
// Get an instance of the controller from the testing module appController = app.get<AppController>(AppController); });
// Nested test suite focusing on the root endpoint describe("root", () => { // Individual test case checking if getHello returns the expected string it('should return "Hello World!"', () => { // Assert that the controller's getHello method returns "Hello World!" expect(appController.getHello()).toBe("Hello World!"); }); });});
Development mode
To run the application in development mode, use the following command. This will start the application in watch mode, which means the server will automatically reload when you make changes to the code.
pnpm run start:dev
Linting
To lint the application code, use the following command. This will check the code for any linting errors and provide suggestions for fixing them.
pnpm run lint