How to create and use configurations, constants, etc values in service provider classes in Nestjs?

February 1, 2023 - 7 min read

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 called useValue, then you have to define a name or token for the object or the provider using the key called provide.

  • 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 the constructor 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 😃.