Hi, there is a class MyClass decorated with @Injectable() that seems to be instantiated and pulled in to other modules implicitly through dependency injection. I'm interested in instantiating MyClass but explicitly providing one of its dependencies, similar to how { provide, useValue } works with the providers in Test.createTestingModule. Is this possible with the NestJS API?
#instantiate module with explicit provider
20 messages · Page 1 of 1 (latest)
You can use a custom provider (the provider/useValue combo) in a regular module
How? I need to do this at runtime. I was looking at the documentation for ModuleRef but it didn't seem possible there.
Maybe pseudo-code or actual code can help clarify what you're trying to do here
There is a service decorated with @Injectable() resembling
@Injectable()
export class A {}
@Injectable()
export class B {}
@Injectable()
export class Service {
constructor(
private readonly a: A,
private readonly b: B,
)
}
And instead of instantiating it through dependency resolution I want to instantiate it with a specific value available at runtime when handling a request. (This happens to be in a resolver somewhere.) So instead of using dependency resolution to get an instance of B as the second parameter to the constructor, I want to provide a specific value. Similar to how one would do this without using dependency injection new Service(..., new B())
Okay, do you still want the value of A to be what it would already be (the instance Nest created) and do you want to do this during a method call, or during application startup when Nest is creating all the other providers?
Well I guess it's actually a little weirder now that I think of it, because if A depends on B then I want A to also use the B I provide a value for... Which I imagine is what the testing module will do.
I need to do this when handling a request, not at startup. And I don't especially care if it uses a new instance of A or not.
If you're doing this at runtime during a request, any reason to not just call new Service(param1, param2) yourself?
Yeah maybe, I don't want to sidestep the framework if I don't have to in case there's magic that is going on that I don't know about.
Well, I suppose you could make a REQUEST scoped provider, sounds like that might help, but I don't know if there's really a need. I guess without knowing the full use case it's hard to say
Right, the use case is that the author of this code wrote services that interact with a database through a database pool instead of a transaction. And I'd like to re-use this logic in the service but providing a transaction instead of a connection pool.
Yeah, I think just calling new yourself would be the best thing here? Unless you create the transaction at the request start in the REQUEST scope, but that's probably not the case
Yeah I mean it seems like having all the logic in these classes is only useful if you're using dependency resolution so bypassing that and doing it myself is more work than moving the logic out and doing something more traditional.
It's just a little surprising to me that this feature exists for automated testing but not in the core api.
I mean, you can absolutely use custom providers where you end up creating your own version of Service using useFactory and new Service(param1, customParam2), no problem. It's more of how you get customParam2 that would be the issue here
I mean in my function I can begin a transaction and then it's in scope. Getting the value I want to inject is not difficult.
So the dependency is created during the request time, and thus, the provider would need to be created after the transaction is. That transaction is created in your code so the framework wouldn't know how to work with it.
I'm kind of curious how people do this in their other projects. It seems like put business logic in services to query the database there, but if services are long-lived instances that do not use a transaction I don't know how that logic can be reused by other services that might need transactions.
Like the examples in nest for sequelize and typeorm are very simple and contain a single model. But if you were to write another service that called the user service to get a user with some id, there's no nice way to re-use that service in a transaction?