Dependency Injection in Nest.js
Tags: nestjs, mongodb, node, typescript
Published: 2020-06-22 08:54:26

Dependency Injection

We have a project module and a bid module.
The project record(in MongoDB) is created by user of type "Sme" and 
the bid record(in MongoDB) is created by user of type "Sponsor".
A **Sponsor** can **bid** for a **project created** by **Sme**.

1.The Project module is shown below with the path 
*src/sme-project/sme-project.module.ts.*
The BidDetailsModule is included within this SmeProjectModule.
Note here that the **SmeProjectService class** is **exported** from **this module** and can be **injected** in other modules.
The **SmeProjectService** class is injected in the **BidDetailsService** class in the later part.
**Code (Part-I):**
{% runkit
// hidden setup JavaScript code goes in this preamble area
const hiddenVar = 42
%}
import { Module } from "@nestjs/common";
import { SmeProjectController } from "./sme-project.controller";
import { SmeProjectService } from "./sme-project.service";
import { MongooseModule } from "@nestjs/mongoose";
import { SmeProjectSchema } from "./objects/sme-project.schema";
import { ProjectComplexityModule } from "../project-complexity/project-complexity.module";
import { PracticeAreaModule } from "../practice-area/practice-area.module";
import { MilestoneModule } from "../milestone/milestone.module";
import { RemarksModule } from "../remarks/remarks.module";
import { BidDetailsModule } from "../bid-details/bid-details.module";
import { ProjectStatusModule } from "../project-status/project-status.module";

@Module({
  imports: [
    MongooseModule.forFeature([
      { name: "SmeProject", schema: SmeProjectSchema },
    ]),
    ProjectComplexityModule,
    PracticeAreaModule,
    MilestoneModule,
    ProjectStatusModule,
    RemarksModule,
    **BidDetailsModule**
  ],
**exports: [SmeProjectService],**
  controllers: [SmeProjectController],
  providers: [SmeProjectService],
})
export class SmeProjectModule {}
{% endrunkit %}
The **BidDetailsModule** module is shown below with the path *src/bid-details/bid-details.module.ts.*
**Code(Part-II):**
{% runkit
// hidden setup JavaScript code goes in this preamble area
const hiddenVar = 42
%}
import { Module, forwardRef } from '@nestjs/common';
import { BidDetailsController } from './bid-details.controller';
import { BidDetailsService } from './bid-details.service';
import { BidDetailsSchema } from './objects/bid-details.schema';
import { MongooseModule } from '@nestjs/mongoose';
import { WalletTransactionsService } from '../wallet-transactions/wallet-transactions.service';
import { WalletTransactionsModule } from '../wallet-transactions/wallet-transactions.module';
import { WalletTransactionsSchema } from '../wallet-transactions/objects/wallet-transactions.schema';
import { UsersModule } from '../users/users.module';
import { UserSchema } from '../users/objects/user.schema';
import { SmeProjectSchema } from '../sme-project/objects/sme-project.schema';
import { SmeProjectModule } from '../sme-project/sme-project.module';
import { SmeProjectService } from '../sme-project/sme-project.service';

@Module({
  imports: [
    MongooseModule.forFeature([
      { name: "BidDetails", schema: BidDetailsSchema },
      { name: "WalletTransaction", schema: WalletTransactionsSchema },
      { name: "User", schema: UserSchema },
      { name: "SmeProject", schema: SmeProjectSchema },
    ]),
    WalletTransactionsModule,
    forwardRef(() => UsersModule),
    **forwardRef(() => SmeProjectModule),**
    //SmeProjectModule,
  ],
  exports: [BidDetailsService, WalletTransactionsService],
  controllers: [BidDetailsController],
  providers: [BidDetailsService, WalletTransactionsService,**SmeProjectService**]
})
export class BidDetailsModule {}
{% endrunkit %}
We need to inject the **SmeProjectService** class in the **BidDetailsService** class in the *constructor* as shown below.So we have imported SmeProjectModule inside BidDetailsModule.We have also **included** the **SmeProjectService** in the **providers** of this **BidDetailsModule**.
Since **BidDetailsModule** is already included in the **SmeProjectModule** Code(Part-I),importing it directly will lead to **circular dependency**.
We use **forwardRef(() => SmeProjectModule)** to solve this in place of just SmeProjectModule.


The **BidDetailsService** class is shown below with the path *src/bid-details/bid-details.service.ts.*
**Code(Part-III):**

{% runkit
// hidden setup JavaScript code goes in this preamble area
const hiddenVar = 42
%}
// visible, reader-editable JavaScript code goes here
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from "mongoose";
import { BaseService } from '../common/base/base.service';
import { IBidDetails } from './objects/bid-details.schema';
import { CreateWalletTransactionDto } from '../wallet-transactions/objects/wallet-transactions.dto';
import { TRANSACTION_TYPE, USER_TYPES } from '../common/constants/enum';
import { WalletTransactionsService } from '../wallet-transactions/wallet-transactions.service';
import { UsersService } from '../users/users.service';
import { EXISTS, TOKENS_FOR_SUBMISSION_ERROR } from '../common/constants/string';
import { IUser } from '../users/objects/user.schema';
import { SmeProjectService } from '../sme-project/sme-project.service';

@Injectable()
export class **BidDetailsService** extends BaseService<IBidDetails> {
    constructor(
        @InjectModel("BidDetails") private readonly bidDetailsModel: Model<IBidDetails>,
       private walletTransactionsService: WalletTransactionsService,
       private usersService: UsersService,
       **private smeProjectService: SmeProjectService**,
      ) {
        super(bidDetailsModel);
      }
     //Details of code...
}

{% endrunkit %}
This is a sample of how dependencies can be worked in Nest.js.
My Github Profile for code:
Please see the develop branch in my repo.
[Link]https://github.com/krishnakurtakoti/nestTwo
{% user krishnakurtakoti %}