In this post, we will look at how to share NestJS Service between Modules. This is a common requirement when building NestJS applications using Modules.

We will be following a step-by-step approach in this post. This will help understanding the various pieces of configuration with great clarity.

1 – Creating a Module and Service

First step is to create a new module and the service we want to share with other modules. To make the example simple, we will create a LoggingService. Basically, this service will only have one method that logs the incoming string to the console.

See below code:

import { Injectable } from "@nestjs/common";

@Injectable()
export class LoggingService {

    logToConsole(logString: string) {
        console.log(logString)
    }
}

Please note that this is not a real logging example and just for demonstration purpose. We annotate this service with the @Injectable decorator. Basically, this decorator specifies that LoggingService is a provider. Read more about NestJS Providers in case you are new to the term.

Next, we declare the LoggingModule as below:

import { Module } from "@nestjs/common";
import { LoggingService } from "./logging.service";

@Module({
    exports: [LoggingService],
})
export class LoggingModule {}

Here, we use the exports array to specify that we wish to export the LoggingService.

2 – Share NestJS Service in Another Module

Next step is to create another module where we wish to use our LoggingModule.

See below code from the BookModule.

import { Module } from "@nestjs/common";
import { LoggingModule } from "src/logging/logging.module";
import { BookController } from "./book.controller";
import { BooksService } from "./books.service";


@Module({
    controllers: [BookController],
    providers: [BooksService],
    imports: [LoggingModule]
})
export class BooksModule {

}

As you can see, our imports array is having the LoggingModule. Basically, we are telling NestJS that we wish to use the services provided by the LoggingModule in the BookModule.

If we don’t import the LoggingModule, we get the below error while trying to start our application.

ERROR [ExceptionHandler] Nest can't resolve dependencies of the BookController (BooksService, ?). Please make sure that the argument LoggingService at index [1] is available in the BooksModule context.

Potential solutions:
- If LoggingService is a provider, is it part of the current BooksModule?
- If LoggingService is exported from a separate @Module, is that module imported within BooksModule?
  @Module({
    imports: [ /* the Module containing LoggingService */ ]
  })

As you can decipher by the message, NestJS will not be able to resolve the dependencies of the BookController since it knows nothing about the LoggingService.

However, since we already imported the LoggingModule, things will work fine.

We can now use the LoggingService in the BookController. See below code:

import { Controller, Get, Body, HttpCode, Post} from "@nestjs/common";
import { LoggingService } from "src/logging/logging.service";
import { Book } from "./book.interface";
import { BooksService } from "./books.service";


@Controller('books')
export class BookController {

    constructor(private booksService: BooksService, private loggingService: LoggingService) {}

    @Get()
    @HttpCode(200)
    async findAll(): Promise<Book[]> {
        this.loggingService.logToConsole("Fetch All Request Received")
        return this.booksService.findAll()
    }

    @Post()
    @HttpCode(201)
    async create(@Body() book: Book){
        this.loggingService.logToConsole("Create New Book Request Received: " + book)
        this.booksService.create(book);
    }
}

Here, we are injecting the LoggingService in the BookController using the constructor. If you wish to know more about how to create controllers, you can refer to the detailed post about NestJS Controllers.

Your guess might be that things will start working now.

However, if we try to start the application using npm run start at this point, we will get the below error message.

ERROR [ExceptionHandler] Nest cannot export a provider/module that is not a part of the currently processed module (LoggingModule). Please verify whether the exported LoggingService is available in this particular context.

3 – Providing the Service

What does the error message in the previous section mean?

Basically, it simply means that the provider (in this case the LoggingService) that we are trying to export is not registered as a provider.

To fix this, we simply need to add the LoggingService in the list of providers in the LoggingModule.

import { Module } from "@nestjs/common";
import { LoggingService } from "./logging.service";

@Module({
    providers: [LoggingService],
    exports: [LoggingService],
})
export class LoggingModule {}

If we start the application now, the previous error is gone and the application starts up fine. Upon hitting the endpoint, we will see the console messages printed by the LoggingService.

Conclusion

With this, we have successfully learnt how to share NestJS service between modules. We looked at each configuration step and the error situations that may arise in case we miss a particular configuration.

If you have any comments or queries about this, please feel free to write in the comments section below.


NestJS is a fundamental pillar in my Cloud & Backend learning path. To know more, don’t forget to subscribe to the Progressive Coder newsletter.

Also, say ‘Hi’ on Twitter for more real-time updates on what’s happening at Progressive Coder.

Categories: BlogNestJS

Saurabh Dashora

Saurabh is a Software Architect with over 12 years of experience. He has worked on large-scale distributed systems across various domains and organizations. He is also a passionate Technical Writer and loves sharing knowledge in the community.

2 Comments

Anton · July 12, 2023 at 2:56 pm

Great information. Exactly what i needed.
Thank you!

    Saurabh Dashora · July 18, 2023 at 1:01 am

    Glad it was useful!

Leave a Reply

Your email address will not be published. Required fields are marked *