Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject service into imported service Nestjs

Tags:

nestjs

I have custom module AuthModule with AuthService, AuthController with routes and so on, that work fine, and want to share this module between several projects as a package. The questions is how to extend imported AuthService from this package and how to inject in it additional services?

More details

Into my custom AuthService, that I want to place in package, is injected class UserService, that by default gets from the database some User data and return it to client side . I need to inject into AuthService another, for example ProfileService from application, that get from database User extra data. The aim is to merge User main data and User extra data, and return this bunch to client

like image 998
Vitalii Del Vorobioff Avatar asked Jun 07 '18 04:06

Vitalii Del Vorobioff


People also ask

How does NestJS dependency injection work?

Dependency injection is an inversion of control (IoC) technique wherein you delegate instantiation of dependencies to the IoC container (in our case, the NestJS runtime system), instead of doing it in your own code imperatively.

What are injectables in NestJS?

@Injectable() is how you tell Nest this is a class that can have dependencies that should be instantiated by Nest and its DI system. The code you posted works because there are no injected dependencies.

What is service in NestJS?

Service. In enterprise applications, we follow the SOLID principle, where S stands for Single Responsibility . The controllers are responsible for accepting HTTP requests from the client and providing a response. For providing the response, you may need to connect to some external source for data.

What is DTO NestJS?

A DTO is an object that defines how the data will be sent over the network. We could determine the DTO schema by using TypeScript interfaces, or by simple classes. Interestingly, we recommend using classes here.


2 Answers

I don't see really the need for a Dynamic Module here.

Indeed, only is needed that the service you want to inject into other entity managed by NestJs, is exported from your AuthModule, and AuthModule imported in the Module you want other entities have injected your AuthService.

import { Module } from '@nestjs/common'
import { AuthService } from './AuthService'

@Module({
  providers: [
    AuthService,
    // ... others
  ],
  exports: [
    AuthService
  ]
})
export class CommonModule {}

Then in your dependent class (let's say another Controller, but could be anything like a GraphQL Resolver, Interceptor, or whatever), you declare the dependency on AuthService.

import { AuthService } from '../auth/AuthService'
import { Dependencies } from '@nestjs/common'

@Dependencies(AuthService)
export class DependentController {
  constructor (authService) {
    this.authService = authService
  }
}

Finally, in order to the AuthService be available to the dependent controller, it has to be imported in the same Module that controller is provided.

import { Module } from '@nestjs/common'
import { CommonModule } from '../auth/CommonModule'
import { DependentController } from './controller/DependentController'

@Module({
  imports: [
    CommonModule,
    // ...others
  ],
  providers: [
    DependentController,
    // ...others
  ]
})
export class ControllerModule {}

I understand that the syntax could be shorter and without using Dependencies decorator in typescript, however the core of the matter is exporting the shared Service from the Module it is provided, then importing that module into the Module other classes that require it.

like image 79
Jesús Franco Avatar answered Sep 24 '22 14:09

Jesús Franco


This is one of the use cases Dynamic Modules have been created for.

import { Module, DynamicModule } from '@nestjs/common';
import { createDatabaseProviders } from './database.providers';
import { Connection } from './connection.provider';

@Module({
  providers: [Connection],
})
export class DatabaseModule {
  static forRoot(entities = [], options?): DynamicModule {
    const providers = createDatabaseProviders(options, entities);
    return {
      module: DatabaseModule,
      providers: providers,
      exports: providers,
    };
  }
}

In this example, see how providers are given (dynamically) to the result module.

Your package should follow the same pattern: expose a static method which allows building a DynamicModule, so you can resolve your other services (internal or external) as you want (building your own array of providers).

like image 32
VinceOPS Avatar answered Sep 23 '22 14:09

VinceOPS