Injecting dependency into `useFactory` results in error.
Describe the bug
From version 5.1.5 (PR)
ImportingMikroOrm with forRootAsync and injecting any dependency in useFactory results in error.
Stack trace
TypeError: Cannot read properties of undefined (reading 'get')
at Object.useFactory (/home/jdr/Workspace/xxx/src/api/core/core.module.ts:15:33)
at Function.createEntityManager (/home/jdr/Workspace/xxx/node_modules/@mikro-orm/nestjs/mikro-orm-core.module.js:125:65)
at Function.forRootAsync (/home/jdr/Workspace/xxx/node_modules/@mikro-orm/nestjs/mikro-orm-core.module.js:89:31)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
To Reproduce
Steps to reproduce the behavior:
Use MikroOrmModule.forRootAsync() and inject any dependency to useFactory.
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
MikroOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: async (configService) => {
return {
entities: [
'./dist/domain/**/model/*.js',
],
dbName: configService.get('database.name'),
type: 'postgresql',
user: configService.get('database.user'),
password: configService.get('database.password'),
port: configService.get('database.port'),
host: configService.get('database.host'),
migrations: {
path: __dirname + './dist/persistence/migrations',
pattern: /^[\w-]+\d+\.js$/,
},
};
},
})
]
})
Expected behavior You should be able to use async provider without any errors thrown.
Versions
| Dependency | Version |
|---|---|
| node | 16.13.2 |
| typescript | 4.9.4 |
| mikro-orm | 5.6.2 |
| mikro-orm/nestjs | 5.1.5 |
When I import ConfigModule (Without isGlobal) it works fine.
I have similar problem, I'm using forRootAsync with contextName: redshift, then I get an error when I want to use MikroORMModule.forFeature
Error: Nest can't resolve dependencies of the InactiveCustomerEntityRepository_redshift (?). Please make sure that the argument redshift_EntityManager at index [0] is available in the MikroOrmModule context.
I kinda doubt this is something fixable from this package, its nest DI that is responsible for the injection.
But it's working just fine with prior versions
I've linked PR that breaks it
Just look at what the PR does, how come it would be connected to nest DI not injecting a dependency? If it is, it still sounds like a nestjs bug to me.
Could somebody provide a repository with this bug, not just the streets above but something I could just clone and start playing with, and I'll try to see if I can figure out what's up here?
This line seems suspicious to me. if someone sets up a useFactory in the async registration that has a value pissed to it, like the ConfigServive, but it's called directly without paying any necessary parameters, then an error like the one above would definitely be present
Can confirm that this issue arose for me after upgrading from 5.1.2 to 5.1.5. I've fallen back to 5.1.2 for now.
This line seems suspicious to me. if someone sets up a useFactory in the async registration that has a value pissed to it, like the ConfigServive, but it's called directly without paying any necessary parameters, then an error like the one above would definitely be present
Right, I moved this into try/catch block to get around it but forgot it can be async as well.
Could you suggest a better way to let nest DI inject the dependencies? The idea behind those changes was to get resolve the same options as the ORM will get, and register the EM flavor based on the driver.
I think you could probably create the entity manager as a provider so that the options can be injected into a factory for it. Would require a bit of re-work, but I think I might be able to help with that this week? I'll have to clone the repo and see what can be done there
That would be great!
@B4nan question: if knex or mongo entity managers are available, should they override the original MikroORM entity manager?
Also, is there anywhere you would prefer to have brief conversation about the code other than this issue? I'm fine with here if that's your preference just want to make sure
Both should work, the one from core as well as the driver-specific implementation. They should resolve to the same - during runtime, it will be always the driver-specific implementation, but it's valid to inject it based on the import from core too. So in a way, those are just aliases. In the next major, if we find a good way to do what 5.1.5 tries to do, I'd like to drop the "old way" in favor of it, this shouldn't be driven by what package is installed.
Also, is there anywhere you would prefer to have brief conversation about the code other than this issue? I'm fine with here if that's your preference just want to make sure
It's fine here, or feel free to join the slack channel, I am there most of the time. I can do discord as well, but I don't keep that app open most of the time (unlike slack).
If you pass contextname in the root (at the same level with useFactory), it works for me.
I did a quick and dirty hotfix by awaiting the useFactory, which should fix the try/catch block. Keeping this open till we find a proper way.
Available in v5.1.6
Closing as resolved via #166, will be part of v5.2.4