create-nestjs-middleware-module icon indicating copy to clipboard operation
create-nestjs-middleware-module copied to clipboard

[QUESTION] Is it possible to use Dependency Injection inside?

Open VladStepanov opened this issue 2 years ago • 2 comments

Have you read the whole documentation?

Is there an existing issue for this?

  • [X] I have searched the existing issues

Question

Is it possible to use Dependency Injection inside createModule?

Additional context

No response

VladStepanov avatar Dec 01 '21 16:12 VladStepanov

At the moment it's not possible. Could you describe how you see this feature? What API should be for it?

iamolegga avatar Dec 01 '21 20:12 iamolegga

Edit: Seems I was too eager. The ModuleRef has no access even to services from @Global() Modules.

I was searching hours for a good solution on configurable+DI supported middlewares. Finally when I found this lib I also found an idea on how to implement it. It's a pretty individual solution and some may find it a bit dirty. But maybe it will inspire someone to do a better setup (passing required DI into createModule for example).

The issue: Functional middleware is easily configurable but lacks DI. Class-based middleware can use DI but configuration is quite messy to do.

I did a little modification to copied source code:

    constructor(
      @Inject(optionsToken)
      private readonly options: SyncOptions<T> | null,
      private moduleRef:ModuleRef // inject moduleRef
    ) {}

    configure(consumer: MiddlewareConsumer) {
      this.options.moduleRef = this.moduleRef; // assign moduleRef to options
      //...

this way, all middlewares wrapped with createModule will receive a moduleRef within their options object. It's a dirty trick - but still the cleanest solution that I could find to reduce duplicate code and setup complexity. Now I can set up the middleware in a clean way:

ApiRateLimitModule.forRootAsync({
	useFactory: async () => {
		return { 
			id: 'AccesscodesController',
			forRoutes: [MaintenanceLoginAsUserController]
		}
	}
}),

and within the middleware, I have access to global DI services by using options.moduleRef.get(ThatDarnServiceINeed)

jbjhjm avatar Jan 19 '22 17:01 jbjhjm