Guide on setting up multiple Axios instances in NestJS

I'm in the process of migrating an existing Express application to NestJS. Currently, I have a configuration file where I define multiple axios instances for each microservice:

export const writeModelApi = axios.create({
  baseURL: getWriteModelApiUrl(),
});

export const readModelApi = axios.create({
  baseURL: getReadModelApiUrl(),
});

export const configApi = axios.create({
  baseURL: getConfigApiUrl(),
});

function addCamelizeInterceptors(api: any) {
  // Interceptor logic
}

addCamelizeInterceptors(taskingApi);
addCamelizeInterceptors(readModelApi);
addCamelizeInterceptors(configApi);

I've been thinking about how to replicate this functionality using shared modules in NestJS. Currently, I have set up the following:

  • ReadModelModule
@Module({
  imports: [
    HttpModule.register({
      baseURL: getReadModelApiUrl(),
    }),
  ],
  providers: [ReadModelService],
  exports: [ReadModelService],
})
export class ReadModelModule implements OnModuleInit {
  constructor(@Inject() private httpService: ReadModelService) {}

  public onModuleInit() {
    addCamelizeInterceptors(this.httpService.axiosRef);
  }
}

  • ReadModelService
@Injectable()
export class ReadModelService extends HttpService {}

However, Nest is throwing an error message that reads:

[ExceptionHandler] Nest can't resolve dependencies of the ReadModelModule (?). Please make sure that the argument dependency at index [0] is available in the ReadModelModule context.

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

I'm struggling with resolving this issue and would appreciate any guidance or help. Thank you!

Answer №1

After some exploration, I came up with a creative workaround. While going through the NestJs code, I discovered that extending the HttpService was not straightforward due to the unavailability of the provider constant (AXIOS_INSTANCE_TOKEN) required for its constructor.

To resolve this limitation, I developed my own version of the HttpModule and included the essential constant to enable my service to extend HttpService seamlessly.

Below is the snippet of my solution:

MyHttpModule:

export const AXIOS_INSTANCE_TOKEN = "AXIOS_INSTANCE_TOKEN";

@Module({
  providers: [
    ReadModelService,
    {
      provide: AXIOS_INSTANCE_TOKEN,
      useValue: Axios,
    },
  ],
  exports: [ReadModelService],
})
export class MyHttpModule {}

ReadModelService:

@Injectable()
export class ReadModelService extends HttpService {
  constructor() {
    const instance = Axios.create({
      baseURL: getReadModelApiUrl(),
    });
    addCamelizeInterceptors(instance);

    super(instance);
  }
}

With this implementation, I can utilize the ReadModelService similarly to HttpService but with added functionalities such as baseURL and axios interceptors. Furthermore, I have replicated a similar approach for WriteModelService and other services. While this might not be the most optimal solution available, it serves its purpose effectively with minimal code necessary.

Answer №2

Consider including HttpService in the providers: [] array within the ReadModelModule

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to incorporate conditional checks prior to running class methods

Seeking input on handling async data retrieval elegantly. When initializing a class with asynchronous data, I have been following this approach: class SomeClass { // Disabling strictPropertyInitialization private someProperty: SomeType public asy ...

Vue's computed property utilizing typed variables

I am trying to create a computed array of type Todo[], but I keep encountering this specific error: No overload matches this call. Overload 1 of 2, '(getter: ComputedGetter<Todo[]>, debugOptions?: DebuggerOptions | undefined): ComputedRef<T ...

Ways to troubleshoot unexpected http requests (404 response) using Axios

When making the HTTP request, everything works smoothly. However, there is an unexpected additional request to /%3Canonymous%3E that results in a 404 error. This is triggering the following error message in Redux: Unhandled Rejection (TypeError): Cannot ...

Tabulate the number of items in an array based on the month and

I have received JSON data with dates indicating the creation time of multiple parcels. I want to analyze this data and calculate the total number of parcels created in each month. I am new to this process and unsure about which thread on Stack Overflow can ...

The Tools of the Trade: TypeScript Tooling

Trying out the amazing Breeze Typescript Entity Generator tool but encountering an error consistently. Error: Experiencing difficulty in locating the default implementation of the 'modelLibrary' interface. Options include 'ko', 'b ...

What categories do input events fall into within Vue?

What Typescript types should be used for input events in Vue to avoid missing target value, key, or files properties when using Event? For example: <input @input="(e: MISSING_TYPE) => {}" /> <input @keypress="(e: MISSING_TYPE) = ...

I will not be accessing the function inside the .on("click") event handler

Can someone help me troubleshoot why my code is not entering the on click function as expected? What am I missing here? let allDivsOnTheRightPane = rightPane.contents().find(".x-panel-body-noheader > div"); //adjust height of expanded divs after addi ...

Guide on implementing a cordova plugin in a TypeScript cordova application

In my Cordova project, which utilizes Angular and Typescript, I am facing issues with implementing the juspay-ec-sdk-plugin for Cordova. I have explored possible solutions on StackOverflow related to integrating Cordova plugin in an Angular 4 Typescript ...

Adding a component to a page in Angular 4: A step-by-step guide

Currently engaged in a project that involves creating a mobile application design within a web application. I'm wondering how to display my Component object on a page using ViewChild? I have a list of PageComponents, below is the PageComponent class ...

Brand new Angular 9 application encountering the error message "ERROR in Cannot read property 'flags' of undefined" when running "ng build" on a Mac device

I set up a fresh Angular 9 project on my MacBook by executing ng new demo (no routing, CSS) cd demo ng build However, I encountered the following error: ERROR in Cannot read property 'flags' of undefined When running "ng version", here's ...

How does the highlighting feature in Fuse.js includeMatches function operate?

Currently, in my Next JS/Typescript web application, I am using the Fuse.js library. However, I am still uncertain about how the includeMatches option functions for highlighting purposes. Whenever I enable this option, I receive a matches object within the ...

Exploring the functionality of angular reactive forms in creating intricate JSON structures

After numerous attempts to resolve the issue on my own, I am reaching out to an Angular developer for assistance. My goal is to display a JSON object in the UI: Here is the JSON Object : items={"departure":"New York","arrival":"California","stations":[ ...

Enhancing many-to-many relationships with additional fields in Objection.js

I have a question that I haven't been able to find a clear answer to in the objection.js documentation. In my scenario, I have two Models: export class Language extends BaseId { name: string; static tableName = 'Languages'; st ...

Changing the default font size has no effect on ChartJS

I'm trying to customize the font size for a chart by changing the default value from 40px to 14px. However, when I set Chart.defaults.global.defaultFontSize to 14, the changes don't seem to take effect. Below is the code snippet for reference. An ...

When NestJS injects an ObjectionJS model, it encounters an exception

Whenever I attempt to inject an Objection.js model into a NestJs service: constructor(@Inject('UserModel') private readonly modelClass: ModelClass<UserModel>) {} I encounter a compile time error stating Maximum call stack size exceeded. I ...

Potential keys + keys that are present in the `initialData`

Is there a way to specify the type of data in order to include all keys that exist in initialData plus additional keys from Item as Partial(optional)? class TrackedInstance<Item extends Record<string, any>, InitialData extends Partial<Item> ...

Getting a date object that is three months prior to the current date in Typescript

I need to retrieve the date object that is 3 months before the current date by using the following code snippet: toDate = new Date(); fromDate = this.toDate.getMonth() - 3; The issue I am facing is that the variable fromDate only contains a number, but I ...

What causes the createResource error to become undefined when it is refetched before being properly set?

How can I access and display the error property for a createResource? In this scenario, why is the error initially set to undefined before it is thrown? The logging shows that it first displays undefined for the error before eventually getting to line er ...

Create a new visual masterpiece using Canvas by repurposing an

I am currently working on the following code snippet; export default async function draw(elRef : RefObject<HTMLCanvasElement>, tileData : TileProps) { const canvas = elRef.current!; const ctx = canvas.getContext('2d')!; ctx.clearRect( ...

Using Express middleware in a TypeScript Express application

I'm currently converting the backend of an ExpressJS application to Typescript. While working on the auth.routes.ts file, I encountered an issue with the middleware (authMiddleware). It seems like there might be a typing error, as the same code in the ...