To make a module available to other modules without importing in Nestjs is to make the module global by using the @Global()
decorator function from the @nestjs/common
module and then defining it just above the module class that you need to use without importing it.
TL;DR
Filepath: src/cats/cats.module.ts
import { Module, Global } from "@nestjs/common";
import { CatsService } from "./cats.service";
// make the `CatsModule` global using the `@Global()`
// decorator function so that this module can
// be used without importing it explicitly in other modules.
@Global()
@Module({
providers: [CatsService], // <- add the provider here
exports: [CatsService], // <- export the provider here
})
export class CatsModule {}
Filepath: src/cats/cats.service.ts
import { Injectable } from "@nestjs/common";
@Injectable()
export class CatsService {
// returns cat names
getCatNames() {
return ["Luna", "Milo", "Simba", "Oliver", "Loki"];
}
}
Filepath: src/customer/customer.service.ts
import { Injectable } from "@nestjs/common";
import { CatsService } from "../cats/cats.service";
@Injectable()
export class CustomerService {
// declare and initialize an instance of
// the `CatsService` service provider class
constructor(private catsService: CatsService) {}
getCatNames() {
// use the `getCatNames()` method from the `CatsService`
// class to get the list of all the cat names.
return this.catsService.getCatNames();
}
}
Filepath: src/customer/customer.controller.ts
import { Controller, Get } from "@nestjs/common";
import { CustomerService } from "./customer.service";
// make a `/customer` base api endpoint
@Controller("/customers")
export class CustomerController {
constructor(private customerService: CustomerService) {}
// adds a `GET` API of `/cats` to the
// `/customer` base endpoint resulting in
// `/customer/cats` API endpoint.
@Get("/cats")
getCatNames() {
return this.customerService.getCatNames();
}
}
Filepath: src/customer/customer.module.ts
import { Module } from "@nestjs/common";
import { CustomerController } from "./customer.controller";
import { CustomerService } from "./customer.service";
@Module({
controllers: [CustomerController], // <- add the controller here
providers: [CustomerService], // <- add the provider here
})
export class CustomerModule {}
Filepath: src/app.module.ts
import { Module } from "@nestjs/common";
import { CustomerModule } from "./customer/customer.module";
import { CatsModule } from "./cats/cats.module";
@Module({
imports: [CustomerModule, CatsModule], // <- add the global and the customer modules here
})
export class AppModule {}
For example, let's say we have 2 modules where one class is called CatsModule
and the other is called CustomersModule
. We aim to use the CatsModule
without importing it in the CustomersModule
.
To do that, let's first create a CatService
service provider class with a method called getCatNames()
. The getCatNames()
method will return all the names of the cats currently present in the system.
The service provider class will look like this,
Filepath: src/cats/cats.service.ts
import { Injectable } from "@nestjs/common";
@Injectable()
export class CatsService {
// returns cat names
getCatNames() {
return ["Luna", "Milo", "Simba", "Oliver", "Loki"];
}
}
Secondly, let's create the CatsModule
class that exports the service provider CatService
service provider class.
Filepath: src/cats/cats.module.ts
import { Module } from "@nestjs/common";
import { CatsService } from "./cats.service";
@Module({
providers: [CatsService], // <- add the provider here
exports: [CatsService], // <- export the provider here
})
export class CatsModule {}
Now we need to make the CatsModule
class global using the @Global()
decorator function from the @nestjs/common
module and use it just before the @Module()
decorator function of the CatsModule
module class.
It can be done like this,
Filepath: src/cats/cats.module.ts
import { Module, Global } from "@nestjs/common";
import { CatsService } from "./cats.service";
// make the `CatsModule` global using the `@Global()`
// decorator function so that this module can
// be used without importing it explicitly in other modules.
@Global()
@Module({
providers: [CatsService], // <- add the provider here
exports: [CatsService], // <- export the provider here
})
export class CatsModule {}
The CatsModule
module is now global and can be used without importing into other modules.
Now let's make a GET
API endpoint called /customers/cats
in the CustomersModule
module that lists all the cat's names from the CatsModules
.
To know more about a GET
API endpoint see the blog on How to make a simple GET request or an API endpoint in Nestjs?.
The API CustomerModule
, CustomerController
, and the CustomerService
classes look like this,
Filepath: src/customer/customer.module.ts
import { Module } from "@nestjs/common";
import { CustomerController } from "./customer.controller";
import { CustomerService } from "./customer.service";
@Module({
controllers: [CustomerController], // <- add the controller here
providers: [CustomerService], // <- add the provider here
})
export class CustomerModule {}
Filepath: src/customer/customer.controller.ts
import { Controller, Get } from "@nestjs/common";
import { CustomerService } from "./customer.service";
// make a `/customer` base api endpoint
@Controller("/customers")
export class CustomerController {
constructor(private customerService: CustomerService) {}
// adds a `GET` API of `/cats` to the
// `/customer` base endpoint resulting in
// `/customer/cats` API endpoint.
@Get("/cats")
getCatNames() {
return this.customerService.getCatNames();
}
}
Filepath: src/customer/customer.service.ts
import { Injectable } from "@nestjs/common";
@Injectable()
export class CustomerService {
getCatNames() {
// cool code here
}
}
We have our /customer/cats
GET
API endpoint ready.
Finally, we need to use our global CatsModule
module in the CustomerService
service provider class. To do that all we have to do is declare and initialize a private variable called catsService
(this can be anything) in the constructor
method of the CustomerService
service provider class.
It can be done like this,
Filepath: src/customer/customer.service.ts
import { Injectable } from "@nestjs/common";
import { CatsService } from "../cats/cats.service";
@Injectable()
export class CustomerService {
// declare and initialize an instance of
// the `CatsService` service provider class
constructor(private catsService: CatsService) {}
getCatNames() {
// use the `getCatNames()` method from the `CatsService`
// class to get the list of all the cat names.
return this.catsService.getCatNames();
}
}
The thing to note is that since we have declared the CatsModule
as the global module, the Nestjs runtime will automatically inject an instance of the CatsModule
class otherwise we would have to import the CatsModule
in the CustomerModule
module declaration file.
Since we have defined the CatsModule
as global, we also need to import the CatsModule
in the core/root module of the application. In our case, it will be in the src/app.module.ts
file.
Filepath: src/app.module.ts
import { Module } from "@nestjs/common";
import { CustomerModule } from "./customer/customer.module";
import { CatsModule } from "./cats/cats.module";
@Module({
imports: [CustomerModule, CatsModule], // <- add the global and the customer modules here
})
export class AppModule {}
Now if we go to the /customers/cats
API endpoint in the browser you can see all the cat names we have added which proves that the global CatsModule
is working as expected. Yay 🥳!
See the above code live in codesandbox.
That's all 😃.