Skip to content

A thin wrapper around Axios for Nest.js using Promises, because the @nestjs/axios package returns an observable.

License

Notifications You must be signed in to change notification settings

jasonraimondi/nestjs-axios-promise

Repository files navigation

Nest.js Axios Promise

GitHub Workflow Status Test Coverage Maintainability GitHub package.json version NPM Downloads

A thin wrapper around Axios for Nest.js using Promises, because the @nestjs/axios package returns an observable. See #why

Install

pnpm add nestjs-axios-promise

Usage

import { AxiosService } from "./axios.service";

@Module({
  imports: [AxiosModule.register()],
  providers: [MyCustomService],
})
export class AppModule {}
@Injectable()
export class MyCustomService {
  constructor(private readonly http: AxiosService) {}

  async doWork() {
    const response = await this.http.get("/");
    console.log(response);
  }
}

Custom Axios config

@Module({
  imports: [
    AxiosModule.register({
      config: {
        baseURL: "https://example.com",
        headers: {
          "X-My-Header": "Is a value!",
        },
      },
    }),
  ],
})
export class AppModule {}

Register Axios interceptors

Axios interceptors can be configured on Axios clients to intercept requests or responses before they are handled by then or catch.

import { create } from "axios";

const client = create();

client.interceptors.request.use(
  (request) => {
    return request;
  },
  (err) => {
    return err;
  },
  {},
);

client.interceptors.response.use(
  (response) => {
    return response;
  },
  (err) => {
    return err;
  },
  {},
);

However, because NestJS abstracts away the construction of services, including this library's Axios wrapper which makes registering Axios interceptors difficult via the usual approach.

To resolve this, this module provides an additional way to configure interceptors via the module registration configuration:

@Module({
  imports: [
    AxiosModule.register({
      interceptors: {
        request: {
          onFulfilled: (requestConfig) => {
            return requestConfig;
          },
          onRejected: (err) => {
            return err;
          },
          options: {},
        },

        response: {
          onFulfilled: (response) => {
            return response;
          },
          onRejected: (err) => {
            return err;
          },
          options: {},
        },
      },
    }),
  ],
})
export class AppModule {}

Interceptors can still be modified later via the Axios reference on the service:

import { HttpService } from "nestjs-axios-promise";

@Injectable()
export class CatsService {
  public constructor(private readonly httpService: HttpService) {}

  public doThing() {
    this.httpService.axios.interceptors.request.use((requestConfig) => {
      return requestConfig;
    });
    this.httpService.axios.interceptors.request.eject();
  }
}

Why

Because I find our way using a promise

import { AxiosService } from "nestjs-axios-promise";

@Injectable()
export class CatsService {
  private readonly logger = new Logger(CatsService.name);

  constructor(private readonly httpService: AxiosService) {}

  findAll(): Promise<Cat[]> {
    const { data } = await this.httpService
      .get<Cat[]>("http://localhost:3000/cats")
      .catch((error: AxiosError) => {
        this.logger.error(error.response.data);
        throw "An error happened!";
      });
    return data;
  }
}

MUCH more preferable to the NestJS way of using an observable. They're casting their observable to a promise anyways... 🤦

import { catchError, firstValueFrom } from "rxjs";
import { HttpService } from "@nestjs/axios";

@Injectable()
export class CatsService {
  private readonly logger = new Logger(CatsService.name);
  constructor(private readonly httpService: HttpService) {}

  findAll(): Promise<Cat[]> {
    const { data } = await firstValueFrom(
      this.httpService.get<Cat[]>("http://localhost:3000/cats").pipe(
        catchError((error: AxiosError) => {
          this.logger.error(error.response.data);
          throw "An error happened!";
        }),
      ),
    );
    return data;
  }
}

About

A thin wrapper around Axios for Nest.js using Promises, because the @nestjs/axios package returns an observable.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project