To create and use configuration, constants, etc values in service provider classes:
-
First, you have to add the object/class (which can be configuration, constants, etc) to the
providers
array within an object with the key calleduseValue
, then you have to define a name or token for the object or the provider using the key calledprovide
. -
Secondly, to use the configuration object on the service provider classes, you have to import and use the
@Inject()
decorator function from the@nestjs/common
module for a variable in theconstructor
method of the service provider class and pass the token name for the provider to the decorator function. This variable will get injected with methods and properties of the configuration object that can be then used in the service provider class.
TL;DR
Filepath: app.service.ts
import { Injectable, Inject } from "@nestjs/common";
// import the configuration object
import { AppConfig } from "./config/AppConfig";
@Injectable()
export class AppService {
// use the injected configuration provider
// using the `@Inject()` decorator function
// with the provider token name
// in the constructor method.
constructor(@Inject("APP_CONFIG") private appConfig: typeof AppConfig) {}
getDetails() {
// return the configuration details object as the response
return this.appConfig;
}
}
Filepath: app.controller.ts
import { Controller, Get } from "@nestjs/common";
import { AppService } from "./app.service";
@Controller("/details")
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getDetails() {
return this.appService.getDetails();
}
}
Filepath: app.module.ts
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
// import the configuration object
import { AppConfig } from "./config/AppConfig";
@Module({
imports: [],
controllers: [AppController],
providers: [
AppService,
// add the provider here (configuration object in our case)
{
useValue: AppConfig, // <- this should be the provider value that needs to be injected
provide: "APP_CONFIG", // <- this should be the token name for the provider to be injected
},
],
})
export class AppModule {}
For example, let's say we have a GET
API called /details
, which will return the current details of the application in a JSON
format. The current details of the application are stored in a simple configuration object which we have to inject into the service provider class for the API and then return to the user.
NOTE: To know more about creating a GET
API in Nestjs, see the blog on How to make a simple GET request or an API endpoint in Nestjs?.
Let's assume that we have created the GET - /details
API endpoint.
The controller
, service
, and the module
files for the API are respectively shown below,
Filepath: app.controller.ts
import { Controller, Get } from "@nestjs/common";
import { AppService } from "./app.service";
@Controller("/details")
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getDetails() {
return this.appService.getDetails();
}
}
Filepath: app.service.ts
import { Injectable } from "@nestjs/common";
@Injectable()
export class AppService {
getDetails(): string {
return "Hello World!";
}
}
Filepath: app.module.ts
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Now the /details
API is ready and if you request the API for a response, you will get the Hello World
string for now. We aim to change this to the details object for the application.
Let's first create the configuration object inside the src/config
directory and call it AppConfig.ts
.
The file content looks like this,
export const AppConfig = {
name: "My Cool App",
version: "v1.0.0",
description: "My Cool app is a Nestjs bootstrapped application",
apiBasePath: "/api",
apiVersion: "v1",
};
Now we need to import the AppConfig
object and add it to the providers
array of the @Module()
decorator function in the AppModule
class.
It should be an object with a key called useValue
where the value is the AppConfig
object that needs to be injected.
It can be done like this,
Filepath: app.module.ts
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
// import the configuration object
import { AppConfig } from "./config/AppConfig";
@Module({
imports: [],
controllers: [AppController],
providers: [
AppService,
// add the provider here (configuration object in our case)
{
useValue: AppConfig, // <- this should be the provider value that needs to be injected
},
],
})
export class AppModule {}
After that, we need to add another key called provide
inside the object where the value is the token
name for the provider we are injecting.
In our case, let's name it APP_CONFIG
.
It can be done like this,
Filepath: app.module.ts
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
// import the configuration object
import { AppConfig } from "./config/AppConfig";
@Module({
imports: [],
controllers: [AppController],
providers: [
AppService,
// add the provider here (configuration object in our case)
{
useValue: AppConfig, // <- this should be the provider value that needs to be injected
provide: "APP_CONFIG", // <- this should be the token name for the provider to be injected
},
],
})
export class AppModule {}
After adding the provider
, now we need to use the @Inject()
decorator function from the @nestjs/common
module on the constructor
method of the AppService
provider class and pass the provider token
name (configuration provider) as an argument followed by initializing a variable with the type so that we can use the configuration object values in the service provider class.
It can be done like this,
Filepath: app.service.ts
import { Injectable } from "@nestjs/common";
// import the configuration object
import { AppConfig } from "./config/AppConfig";
@Injectable()
export class AppService {
// use the injected configuration provider
// using the `@Inject()` decorator function
// with the provider token name
// in the constructor method.
constructor(@Inject("APP_CONFIG") appConfig: typeof AppConfig);
getDetails(): string {
return "Hello World!";
}
}
NOTE: The typeof
operator when initializing the variable in the constructor is used to get the configuration object's type and structure. If you are using a class definition you won't be needing to use the typeof
operator.
Now after injecting the configuration values and initializing the appConfig
variable, we can use the appConfig
object values in the getDetails()
method. In our case, we need to return the entire configuration object instead of the Hello World
string. This can be done by using the this
operator followed by retrieving the appConfig
property values.
It can be done like this,
Filepath: app.service.ts
import { Injectable, Inject } from "@nestjs/common";
// import the configuration object
import { AppConfig } from "./config/AppConfig";
@Injectable()
export class AppService {
// use the injected configuration provider
// using the `@Inject()` decorator function
// with the provider token name
// in the constructor method.
constructor(@Inject("APP_CONFIG") private appConfig: typeof AppConfig) {}
getDetails() {
// return the configuration details object as the response
return this.appConfig;
}
}
Now if you go to the /details
API endpoint in the browser, you can see a JSON
response like below which is the same as the configuration details object.
{
"name": "My Cool App",
"version": "v1.0.0",
"description": "My Cool app is a Nestjs bootstrapped application",
"apiBasePath": "/api",
"apiVersion": "v1"
}
This is how we can create and use configurations, constants, etc values in Nestjs.
See the above code live in codesandbox.
That's all 😃.