Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling third party dependencies in nest.js

What is the best practice on how to handle third-party dependencies (i.e. dependencies that don't come in the form of a nest-module) in nest?

For example, I'm using morgan in my own logging module directly by importing it in the respective file:

import { Injectable, MiddlewareFunction, NestMiddleware } from '@nestjs/common';
import * as morgan from 'morgan';

@Injectable()
export class NestLoggingMiddleware implements NestMiddleware {

    resolve(...args: any[]): MiddlewareFunction {
        /** use morgan here, e.g. wrap it in a custom middleware ... */
    }
}

Now I know nest's architecture is heavily influenced by Angular, and I found this article explaining how to deal with 3rd party dependencies in angular. Does the same idea apply to nest? Should I create a custom provider for morgan and inject that? And do I inject just the morgan import, or an already configured morgan instance?

like image 829
DeX3 Avatar asked Jan 03 '19 11:01

DeX3


People also ask

How does dependency injection work in NestJS?

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 is @injectable 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 are providers in NestJS?

Providers in Nest are used to create services, factories, helpers, and more that can be injected into controllers and other providers using Nest's built-in dependency injection. The @Injectable() decorator is used to create a provider class.

What is DTO in 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.


1 Answers

Yes, injecting 3rd party dependencies as custom providers is the way to go. You can use an async factory function to inject dependencies needed for the setup configuration. This way, you will have an already configured instance.

This is an example of what I did recently:

import { Telegraf } from 'telegraf';

// ...

providers: [
  {
    provide: Telegraf,
    useFactory: async (configService: ConfigService) => {
      return new Telegraf(configService.telegramToken);
    },
    inject: [ConfigService],
  },
]

Depending on your requirements, it might make sense to create a new module for your dependency that reexports your provider. Instead of directly exporting your 3rd party instance, you can also create a facade service, that encapsulates the dependency. This way, it becomes easier to exchange the library at some later point.

like image 157
Kim Kern Avatar answered Sep 29 '22 03:09

Kim Kern