MacMusic  |  PcMusic  |  440 Software  |  440 Forums  |  440TV  |  Zicos
nest
Search

Intro to Nest.js: Server-side JavaScript development on Node

Wednesday November 26, 2025. 10:00 AM , from InfoWorld
Not to be confused with Next.js, Nest.js is a server-side framework that offers a complete solution for building web applications. Nest is very popular, with over 73,000 stars on GitHub as of this writing. It is an excellent choice if you need to build a server-side application using TypeScript or JavaScript, and if you want a well-thought-out solution with all the architectural components in one place.

Nest out of the box

Nest’s design is philosophically inspired by Angular. At its heart is a dependency injection (DI) engine that wires together all the components using a common mechanism. If you are familiar with Spring Web, you will probably be right at home with Nest.

On top of its DI engine, Nest hosts a variety of useful built-in capabilities, including controllers, providers and modules:

Controllers define HTTP routes and their handlers.

Providers contain the middleware logic used by controllers (often called services in other frameworks).

Modules group together controllers and providers.

Nest also incorporates several additional features worth noting:

Pipes are used for data validation and transformation.

Guards are for authentication and authorization.

Interceptors are a type of AOP support, used for other cross-cutting concerns.

Next, we’ll look at using Nest’s core components in a server-side application.

Nest controllers: Define routes and endpoints

To define a controller class in Nest, you use the @Controller decorator:

import { Controller } from '@nestjs/common';

@Controller('birds') export class BirdsController {
//...
} }

This controller exists at the /birds route and lets us define routes inside that route, where each endpoint is defined with a decorator corresponding to the HTTP method it handles.

For example, if we wanted a GET endpoint inside the /birds route that accepted a type parameter, we could do this:

@Get(':type')
findBirdsByType(@Param('type') type: string): Bird[] {
const birds = birdDatabase[type];
if (!birds) {
throw new NotFoundException(`No birds found for type '${type}'.);
}
return birds;
}

Nest is TypeScript-native, so our birdDatabase might look like this:

interface Bird {
id: number;
name: string;
species: string;
}

const birdDatabase: Record = {
songbird: [
{ id: 1, name: 'Song Sparrow', species: 'Melospiza melodia' },
{ id: 2, name: 'American Robin', species: 'Turdus migratorius' },
{ id: 3, name: 'Eastern Towhee', species: 'Pipilo erythrophthalmus' },
],
raptor: [
{ id: 4, name: 'Red-tailed Hawk', species: 'Buteo jamaicensis' },
{ id: 5, name: 'Peregrine Falcon', species: 'Falco peregrinus' },
{ id: 6, name: 'Bald Eagle', species: 'Haliaeetus leucocephalus' },
],
corvid: [
{ id: 7, name: 'California Scrub-Jay', species: 'Aphelocoma californica' },
{ id: 8, name: 'American Crow', species: 'Corvus brachyrhynchos' },
{ id: 9, name: 'Common Raven', species: 'Corvus corax' },
],
};

Nest automatically converts that code to appropriate JSON, which you then fine-tune as needed.

Nest providers: Separate business logic from HTTP handling

One of the most important principles in organizing web applications as they grow in complexity is to separate concerns into layers. As much as possible, we want to separate the HTTP handling logic from the business logic. To do this, we can extract the latter into a provider (or service) class that is injected into the controller.

Below is an example of a bird provider. The @Injectable decorator instructs Nest to make this class available in the dependency injection engine:

@Injectable()
export class BirdsService {
private readonly birdDatabase: Record = {
//... same bird data as before
};
findByType(type: string): Bird[] {
const birds = this.birdDatabase[type];
if (!birds) {
throw new NotFoundException(`No birds found for type '${type}'.`);
}
return birds;
}
}

Now, in the controller, we can consume the provider and its findByType method like so:

import { BirdsService } from './birds.service';

@Controller('birds')
export class BirdsController {
// Injected provider:
constructor(private readonly birdsService: BirdsService) {}

@Get(':type')
findBirdsByType(@Param('type') type: string) {
// Delegate to the provider:
return this.birdsService.findByType(type);
}
}

Notice that we need to import the BirdsService from the file where it is defined.

Now we have a very simple controller, which deals only with the details of the HTTP request itself. The business logic is all concentrated in the service layer.

Nest modules: Organize your work

To register our controllers and providers with the Nest engine, we need to define a module that contains them:

import { Module } from '@nestjs/common';
import { BirdsController } from './birds.controller';
import { BirdsService } from './birds.service';

@Module({
controllers: [BirdsController],
providers: [BirdsService],
})
export class BirdsModule {}

The classes listed in the providers array will be made available to all other providers and controllers in this module, while the controllers will be made active as handlers.

Although the module definition adds an extra step of work, it is an excellent mechanism for organizing your application. It lets you define areas of your application that are related and keeps them focused. It also limits the amount of code Nest has to scan to find dependencies.

The Nest data layer: Built-in data persistence

The data layer is another common layer in an application architecture. It is where services (providers) go to interact with a persistent datastore like a relational or NoSQL database.

Nest’s module system is quite flexible and can support any datastore, but it has built-in modules for TypeORM, Sequelize and Mongoose, which makes using any of those solutions easier.

Among other things (like defining datastore connection information), a datastore like TypeORM lets you define entities (persistent types) that hold the data going to and from the database. For our example, we could have a TypeORM entity for birds:

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Bird {
@PrimaryGeneratedColumn()
id: number;

@Column()
name: string;

@Column()
species: string;

@Column()
type: 'songbird' | 'raptor' | 'corvid';
}

This entity can be used to expose a repository class (a data layer class). The repository is created by the typeORM tool when we register it in the module system:

//...
import { TypeOrmModule } from '@nestjs/typeorm';
import { Bird } from './bird.entity';

@Module({
imports: [TypeOrmModule.forFeature([Bird])], // Added this
controllers: [BirdsController],
providers: [BirdsService],
})
export class BirdsModule {}

The TypeORMModule function automatically creates various CRUD functions based on the datastore and entity definition. We can then use those in the service layer:

import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Bird } from './bird.entity';

@Injectable()
export class BirdsService {
constructor(
@InjectRepository(Bird) // Bird repository is injected here
private birdsRepository: Repository,
) {}

// NOTE: DB access is async
async findByType(type: string): Promise {
// Actual DB call here instead of in-memory data:
const birds = await this.birdsRepository.find({ where: { type } });

if (!birds || birds.length === 0) {
throw new NotFoundException(`No birds found for type '${type}'.`);
}
return birds;
}
}

Data transfer objects and DTO validation

So far, we have only been reading data. The other side of the coin is accepting data from the user. For this, we use DTOs (data transfer objects). This lets us define the shape of data we take in.

For example, if we wanted to accept a new bird type from the user, it could look something like this:

import { IsString, IsNotEmpty, IsIn } from 'class-validator';

export class CreateBirdDto {
@IsString()
@IsNotEmpty()
name: string;

@IsString()
@IsNotEmpty()
species: string;

// Hardcoding these values for convenience
@IsIn(['songbird', 'raptor', 'corvid'])
type: 'songbird' | 'raptor' | 'corvid';
}

The create-bird.dto describes what values are allowed for the bird-creation process. We can then use this in the controller to add a bird-creation endpoint:

import { CreateBirdDto } from './create-bird.dto';
//...
@Post()
create(@Body() createBirdDto: CreateBirdDto) {
return this.birdsService.create(createBirdDto);
}

We also use it in the bird service provider:

async create(createBirdDto: CreateBirdDto): Promise {
// Uses TypeORM's.create() to make a new bird entity
const newBird = this.birdsRepository.create(createBirdDto);
// TypeORM’s save() method persists the entity:
return this.birdsRepository.save(newBird);
}

Activate the DTO validation with a pipe

Now everything is in place to enforce the rules defined by the DTO. We can make the DTO validator live by telling Nest to use all validators globally:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
const app = await NestFactory.create(AppModule);

// Enable auto-validation for our entire application
app.useGlobalPipes(new ValidationPipe());

await app.listen(3000);
}
bootstrap();

The built-in ValidationPipe will enforce all the DTOs defined in the application. Now, Nest itself will reject requests that don’t meet the DTO’s requirements with a 400 Bad Request.

Conclusion

This article was an overview of the core internal architecture of Nest. In addition to its core components, Nest has excellent CLI support like generators for DTOs and controllers, scaffolding, and development mode, as well as multi-platform deployment targets, such as Node or Fastify, and Docker-friendly builds.

Nest is a full-featured and modern server-side framework for TypeScript and JavaScript. It’s a great option to have for substantial projects that require robust server-side support.
https://www.infoworld.com/article/4091407/intro-to-nest-js-server-side-javascript-development-on-nod...

Related News

News copyright owned by their original publishers | Copyright © 2004 - 2025 Zicos / 440Network
Current Date
Nov, Wed 26 - 11:10 CET