gremo
gremo

Reputation: 48909

Access Nest "injector" in a custom interceptor

I need to access a service (provided by Nest TypeOrmModule) inside the intercept function (important note: not as constructor parameter!!!) because it depends of the passed options (entity in this case).

The service injection token is provided by the getRepositoryToken function.

export class PaginationInterceptor {
  constructor(private readonly entity: Function) {}

  intercept(context: ExecutionContext, call$: Observable<any>): Observable<any> {
    // Here I want to inject the TypeORM repository.
    // I know how to get the injection token, but not HOW to
    // get the "injector" itself.
    const repository = getRepositoryToken(this.entity);

    // stuff...

    return call$;
  }
}

Is any concept of "service container" in Nest? This github issue didn't help me.

Example usage (controller action):

  @Get()
  @UseInterceptors(new PaginationInterceptor(Customer))
  async getAll() {
    // stuff...
  }

Upvotes: 4

Views: 4600

Answers (1)

VinceOPS
VinceOPS

Reputation: 2720

Regarding dependency injection (if you really want/need it), I guess using a mixin class can do the trick. See the v4 documentation (Advanced > Mixin classes).

import { NestInterceptor, ExecutionContext, mixin, Inject } from '@nestjs/common';
import { getRepositoryToken } from '@nestjs/typeorm';
import { Observable } from 'rxjs';
import { Repository } from 'typeorm';

export function mixinPaginationInterceptor<T extends new (...args: any[]) => any>(entityClass: T) {
  // declare the class here as we can't give it "as-is" to `mixin` because of the decorator in its constructor
  class PaginationInterceptor implements NestInterceptor {
    constructor(@Inject(getRepositoryToken(entityClass)) private readonly repository: Repository<T>) {}

    intercept(context: ExecutionContext, $call: Observable<any>) {
      // do your things with `this.repository`
      return $call;
    }
  }

  return mixin(PaginationInterceptor);
}

Disclaimer: this is valid TypeScript code but I didn't had the chance to test it in a real project, so it might need a bit of rework. The idea is to use it like this:

@UseInterceptors(mixinPaginationInterceptor(YourEntityClass))

Let me know if you have any question about the code. But I think the doc about mixin is pretty good!


OR You can also use getRepository from typeorm (passing the entity class). This is not DI, thus, it will oblige you to spyOn the getRepository function in order to do proper testing.


Regarding the container, I'm almost sure that the only way to access it is using the Execution Context, as pointed by Kim.

Upvotes: 6

Related Questions