# Nest JS Understanding power of RX Observables


![](./index.png)

## Nest JS Understanding power of RX Observables

###  What is NestJS?

As described in the [Nestjs](https://nestjs.com) website, Nestjs is *a progressive Node.js framework for building efficient, reliable and scalable server-side applications.* 

Github Link 
https://github.com/tkssharma/blogs/tree/master/nestjs-rest-apis-docs


Nestjs combines the best programming practice and the cutting-edge techniques  from the NodeJS communities. 

* A lot of NestJS concepts are heavily inspired by the effort of the popular frameworks in the world, esp.  [Angular](https://www.angular.io) .
* Nestjs hides the complexities of web programming in NodeJS, it provides a common abstraction of the web request handling,  you are free to choose [Expressjs](https://expressjs.com/) or  [Fastify](https://www.fastify.io) as the background engine.
* Nestjs provides a lot of third party project integrations, from database operations, such as Mongoose, TypeORM, etc. to Message Brokers, such as Redis,   RabbitMQ, etc.

If you are new to Nestjs like me but  has some experience of  [Angular](https://www.angular.io) , [TypeDI](https://github.com/typestack/typedi#usage-with-typescript) or [Spring WebMVC](http://www.spring.io), bootstraping a Nestjs project is really a piece of cake. 

## Generating a NestJS project

Make sure you have installed the latest [Nodejs](https://nodejs.org/en/). 

```bash
npm i -g @nestjs/cli
```

When it is finished, there is a `nest` command available in the `Path`. The usage of `nest` is similar with `ng` (Angular CLI), type `nest --help` in the terminal to list help for all commands.

```bash
❯ nest --help
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.
  update|u [options]                              Update Nest dependencies.
  add [options] <library>                         Adds support for an external library to your project.
  generate|g [options] <schematic> [name] [path]  Generate a Nest element.
    Available schematics:
      ┌───────────────┬─────────────┐
      │ name          │ alias       │
      │ application   │ application │
      │ class         │ cl          │
      │ configuration │ config      │
      │ controller    │ co          │
      │ decorator     │ d           │
      │ filter        │ f           │
      │ gateway       │ ga          │
      │ guard         │ gu          │
      │ interceptor   │ in          │
      │ interface     │ interface   │
      │ middleware    │ mi          │
      │ module        │ mo          │
      │ pipe          │ pi          │
      │ provider      │ pr          │
      │ resolver      │ r           │
      │ service       │ s           │
      │ library       │ lib         │
      │ sub-app       │ app         │
      └───────────────┴─────────────┘
```

 Now generate a Nestjs project via:

```bash
nest new nestjs-sample
```

Open it in your favorite IDEs, such as [Intellij WebStorm](https://www.jetbrains.com/webstorm/) or [VSCode](https://code.visualstudio.com/). 

## Exploring the project files

Expand the project root, you will see the following like tree nodes.

```bash
.
├── LICENSE
├── nest-cli.json
├── package.json
├── package-lock.json
├── README.md
├── 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

```



The default structure of this project is very similar with the one generated by Angular CLI.

* *src/main.ts* is the entry file of this application.
* *src/app\** is the top level component in a nest application.  
  * There is an a*pp.module.ts* is a Nestjs `Module` which is similar with Angular `NgModule`, and used to organize codes in the logic view.
  * The *app.service.ts* is an `@Injectable` component, similar with the service in [Angular](https://spring.io) or Spring's Service, it is used for handling business logic. A service is annotated with `@Injectable`.
  * The *app.controller.ts* is the controller of MVC, to handle incoming request, and responds the handled result back to client. The annotatoin `@Controller()` is similar with Spring MVC's `@Controller`.
  * The *app.controller.spec.ts* is test file for *app.controller.ts*. Nestjs uses [Jest](https://jestjs.io/) as testing framework.
* *test* folder is for storing e2e test files.

We can simple Controller and service in the sample code 
that looks something like this 

```js
import { Get, Post, Body, Put, Delete, Param, Controller, UsePipes } from '@nestjs/common';
import { Request } from 'express';
import { UserService } from './user.service';
import { UserRO } from './user.interface';
import { CreateUserDto, UpdateUserDto, LoginUserDto } from './dto';
import { HttpException } from '@nestjs/common/exceptions/http.exception';
import { User } from './user.decorator';
import { ValidationPipe } from '../shared/pipes/validation.pipe';

import {
  ApiBearerAuth, ApiTags
} from '@nestjs/swagger';

@ApiBearerAuth()
@ApiTags('user')
@Controller()
export class UserController {

  constructor(private readonly userService: UserService) {}

  @Get('user')
  async findMe(@User('email') email: string): Promise<UserRO> {
    return await this.userService.findByEmail(email);
  }

  @Put('user')
  async update(@User('id') userId: number, @Body('user') userData: UpdateUserDto) {
    return await this.userService.update(userId, userData);
  }
}
```

User service 

```js
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, getRepository, DeleteResult } from 'typeorm';
import { UserEntity } from './user.entity';
import {CreateUserDto, LoginUserDto, UpdateUserDto} from './dto';
const jwt = require('jsonwebtoken');
import { SECRET } from '../config';
import { UserRO } from './user.interface';
import { validate } from 'class-validator';
import { HttpException } from '@nestjs/common/exceptions/http.exception';
import { HttpStatus } from '@nestjs/common';
import * as argon2 from 'argon2';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(UserEntity)
    private readonly userRepository: Repository<UserEntity>
  ) {}

  async findAll(): Promise<UserEntity[]> {
    return await this.userRepository.find();
  }

  async findOne({email, password}: LoginUserDto): Promise<UserEntity> {
    const user = await this.userRepository.findOne({email});
    if (!user) {
      return null;
    }

    if (await argon2.verify(user.password, password)) {
      return user;
    }

    return null;
  }
}
```
And Finally main Module 

```js
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { ArticleModule } from './article/article.module';
import { UserModule } from './user/user.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Connection } from 'typeorm';
import { ProfileModule } from './profile/profile.module';
import { TagModule } from './tag/tag.module';

@Module({
  imports: [
    TypeOrmModule.forRoot(),
    ArticleModule,
    UserModule,
    ProfileModule,
    TagModule
  ],
  controllers: [
    AppController
  ],
  providers: []
})
export class ApplicationModule {
  constructor(private readonly connection: Connection) {}
}
```

This is sample how we write the controller and service now lets see how can we do same using observable and RX JS Operators 

RxJS (Reactive Extensions for JavaScript) is a library that provides a set of powerful tools for reactive programming in JavaScript. It is based on the concept of Observables, which are a way to handle asynchronous data streams and perform operations on those streams in a functional and declarative manner.

In traditional programming, you typically write imperative code that explicitly specifies how to perform actions and handle data. However, with RxJS and the concept of Observables, you can write code that reacts to changes in data and events, allowing you to build more flexible and responsive applications.

Observables represent data streams over time. They can emit multiple values, including asynchronous data such as HTTP responses, events, or user input. Observables can be created from various sources such as arrays, events, timers, or even custom sources.

Observables provide a wide range of operators that allow you to transform, filter, combine, and manipulate the data streams. These operators follow functional programming principles and enable you to create complex data processing pipelines with ease. Some common operators include map, filter, reduce, merge, and debounce, among many others.

One of the key benefits of using Observables is that they support composition. You can combine multiple observables, apply operators to them, and create new observables as a result. This composability makes it easy to build complex asynchronous workflows and handle data dependencies.

Another important aspect of Observables is that they support handling errors and completion. Observables can emit error notifications when something goes wrong during data processing, allowing you to handle and recover from errors gracefully. They also emit a completion notification when the stream of data has ended, indicating that no more values will be emitted.

Overall, RxJS and Observables provide a powerful and expressive way to handle asynchronous and event-based programming in JavaScript. They enable you to write code that is more reactive, declarative, and efficient when dealing with complex asynchronous scenarios, making it easier to manage and process data streams in a predictable and composable way.

## Using RX JS with Nest JS Project 

Using RxJS with a NestJS application can enhance its capabilities for handling asynchronous operations and creating reactive pipelines. Here are some ways you can integrate RxJS into your NestJS application:

1. Asynchronous Operations: NestJS applications often involve interacting with external services or performing time-consuming operations. RxJS can help manage these asynchronous tasks. You can use Observables to represent asynchronous data streams and apply operators to handle data processing. For example, you can use the `from` operator to convert promises or callback-based functions into Observables.

2. Reactive Controllers: NestJS controllers handle incoming requests and generate responses. By leveraging RxJS, you can create reactive endpoints that respond to changes in data or events. You can use Observables to represent data streams, apply operators to transform the data, and then return the result as a response.

3. Inter-service Communication: In a microservices architecture, NestJS applications may need to communicate with other services. RxJS can facilitate this communication by using Observables as a means of streaming data between services. You can use operators like `switchMap` or `mergeMap` to handle data dependencies and make multiple service calls in a reactive manner.

4. Middleware and Pipes: NestJS provides middleware and pipes for intercepting and modifying incoming requests and outgoing responses. You can use RxJS operators to handle asynchronous operations within middleware or pipes. For example, you can use the `map` operator to transform the data or the `catchError` operator to handle errors.

5. Event-driven Programming: NestJS applications can benefit from event-driven programming, where components react to events and trigger actions accordingly. RxJS provides a rich set of operators to handle event streams. You can use subjects or event emitters as Observables to represent events and use operators like `filter` or `debounceTime` to handle event stream transformations.

6. Testing: RxJS offers testing utilities that can be used to write unit tests for NestJS applications. You can use operators like `toArray` or `toPromise` to convert Observables into arrays or promises, allowing you to assert the emitted values during testing.

Remember to import the necessary RxJS modules, such as `Observable` and required operators, in your NestJS components to start using RxJS functionality effectively within your application.

By integrating RxJS into your NestJS application, you can harness the power of reactive programming, handle asynchronous operations gracefully, and create responsive, event-driven architectures.


Certainly! Here's an example code snippet that demonstrates how to use RxJS within a NestJS application:

```typescript
import { Controller, Get } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Controller('example')
export class ExampleController {
  @Get()
  getData(): Observable<any> {
    return this.fetchData().pipe(
      map(data => {
        // Transform the data using RxJS operators
        return this.processData(data);
      }),
    );
  }

  private fetchData(): Observable<any> {
    // Simulate an asynchronous data retrieval
    return new Observable(observer => {
      setTimeout(() => {
        observer.next('Example data');
        observer.complete();
      }, 1000);
    });
  }

  private processData(data: any): any {
    // Perform some processing on the data
    return data.toUpperCase();
  }
}
```

In the above example, we have a simple NestJS controller with a single endpoint (`/example`) that retrieves and processes data using RxJS. Here's a breakdown of the code:

- We import the necessary modules from `@nestjs/common` and `rxjs`.
- The `ExampleController` class is decorated with the `@Controller` decorator, specifying the base route path as `'example'`.
- The `getData()` method is decorated with `@Get()` to handle HTTP GET requests to the `/example` route.
- Within `getData()`, we call the `fetchData()` method, which returns an Observable representing an asynchronous data retrieval. We simulate this retrieval by using a `setTimeout` function to emit a single value (`'Example data'`) and complete the observable after 1 second.
- The `map` operator is applied to the Observable returned by `fetchData()`. This operator transforms the emitted data by passing it to the `processData()` method, which converts it to uppercase.
- The transformed data is returned as the response of the `/example` endpoint.

This example demonstrates how you can use RxJS to handle asynchronous operations and apply transformations to the data stream within a NestJS controller. You can build upon this foundation to implement more complex asynchronous workflows and handle data dependencies using RxJS operators and observables.

 Here's a continuation of the example code, focusing on consuming the Observable in a NestJS service:

```typescript
import { Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
import { HttpClient } from '@nestjs/common';

@Injectable()
export class ExampleService {
  constructor(private readonly http: HttpClient) {}

  fetchData(): Observable<any> {
    const apiUrl = 'https://api.example.com/data';
    return this.http.get(apiUrl);
  }

  processData(data: any): any {
    // Perform any processing on the data
    return {
      ...data,
      processed: true,
    };
  }
}
```

In this example, we have a NestJS service (`ExampleService`) that is responsible for fetching and processing data using RxJS Observables. Here's an explanation of the code:

- We import the necessary modules from `@nestjs/common` and `rxjs`, including the `HttpClient` module for making HTTP requests.
- The `ExampleService` class is decorated with the `@Injectable()` decorator, indicating that it can be injected as a dependency.
- We inject the `HttpClient` into the service's constructor using dependency injection.
- The `fetchData()` method uses the `http.get()` method from the `HttpClient` to make an HTTP GET request to an API endpoint (`apiUrl`). The method returns an Observable that represents the asynchronous data retrieval.
- The `processData()` method takes the retrieved data and performs any necessary processing on it.
- You can add additional methods to the service to handle further data operations using RxJS operators and observables.

By separating the data retrieval and processing logic into a service, you can leverage the power of RxJS Observables within your NestJS application. This allows you to handle asynchronous operations, make API requests, process data, and respond to events in a reactive and composable manner.

Remember to import the required modules and configure the `HttpClient` module properly in your NestJS application's module file (`app.module.ts`) to enable the use of the `HttpClient` within services.

By utilizing RxJS Observables in your NestJS service, you can create a robust and reactive data pipeline that seamlessly integrates with external APIs, performs data transformations, and enables efficient handling of asynchronous operations.

Another example 

Here's an example of how you can create a NestJS API for a Todo application using RxJS Observables:

```typescript
import { Controller, Get, Post, Body, Param, Delete } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

interface Todo {
  id: string;
  title: string;
  completed: boolean;
}

@Controller('todos')
export class TodoController {
  private todos: Todo[] = [];

  @Get()
  getAllTodos(): Observable<Todo[]> {
    return new Observable(observer => {
      observer.next(this.todos);
      observer.complete();
    });
  }

  @Post()
  createTodo(@Body() todo: Todo): Observable<Todo> {
    return new Observable(observer => {
      this.todos.push(todo);
      observer.next(todo);
      observer.complete();
    });
  }

  @Delete(':id')
  deleteTodoById(@Param('id') id: string): Observable<void> {
    return new Observable(observer => {
      const index = this.todos.findIndex(todo => todo.id === id);
      if (index !== -1) {
        this.todos.splice(index, 1);
      }
      observer.next();
      observer.complete();
    });
  }

  @Post(':id/complete')
  completeTodoById(@Param('id') id: string): Observable<Todo> {
    return new Observable(observer => {
      const todo = this.todos.find(todo => todo.id === id);
      if (todo) {
        todo.completed = true;
        observer.next(todo);
      }
      observer.complete();
    });
  }
}
```

In this example, we have a `TodoController` that handles CRUD operations for a Todo application. Here's an explanation of the code:

- We import the necessary modules from `@nestjs/common` and `rxjs`.
- The `TodoController` class is decorated with the `@Controller` decorator, specifying the base route path as `'todos'`.
- The `getAllTodos()` method handles the GET request to `/todos` and returns an observable that emits the list of todos.
- The `createTodo()` method handles the POST request to `/todos` and returns an observable that emits the created todo.
- The `deleteTodoById()` method handles the DELETE request to `/todos/:id` and returns an observable that emits no value upon successful deletion.
- The `completeTodoById()` method handles the POST request to `/todos/:id/complete` and returns an observable that emits the updated todo upon successful completion.

In this example, we use simple in-memory storage (`this.todos`) to store the todo items. However, you can replace this with a database or any other persistent storage mechanism.

By returning RxJS Observables from the controller methods, you can leverage the power of reactive programming to handle asynchronous operations, perform data transformations, and compose multiple operations using operators such as `map`, `filter`, or `switchMap`.

Remember to import the required modules and configure the routing appropriately in your NestJS application's module file (`app.module.ts`) to enable the use of the `TodoController`.

With this example, you have a foundation for building a Todo API in NestJS using RxJS Observables. You can extend and customize this code to fit the specific needs of your application, including additional CRUD operations, validation, authentication, and more.
