Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MikroOrmModule.forRootAsync ignores MikroOrm provider useFactory function #12

Closed
SimoneDagna opened this issue Jan 8, 2021 · 7 comments
Assignees
Labels
bug Something isn't working

Comments

@SimoneDagna
Copy link

Describe the bug
When importing MikroOrm with forRootAsync and using Factory provider: useFactory the given options are ignored and defaults are used instead.
From the stack trace it looks like it is instantiating MikroOrm class directly instead of using useFactory from the MikroOrm custom provider that uses MikroOrm.init() method.
https://github.com/mikro-orm/nestjs/blob/master/src/mikro-orm.providers.ts#L24
But these are my suppositions and I feel I'm missing something.

Stack trace

[Nest] 65   - 01/08/2021, 9:00:27 PM   [ExceptionHandler] No platform type specified, please fill in `type` or provide custom driver class in `driver` option. Available platforms types: [ 'mongo', 'mysql', 'mariadb', 'postgresql', 'sqlite' ] +30ms
Error: No platform type specified, please fill in `type` or provide custom driver class in `driver` option. Available platforms types: [ 'mongo', 'mysql', 'mariadb', 'postgresql', 'sqlite' ]
    at Configuration.validateOptions (/app/node_modules/@mikro-orm/core/utils/Configuration.js:170:13)
    at new Configuration (/app/node_modules/@mikro-orm/core/utils/Configuration.js:25:12)
    at new MikroORM (/app/node_modules/@mikro-orm/core/MikroORM.js:23:21)
    at Injector.instantiateClass (/app/node_modules/@nestjs/core/injector/injector.js:286:19)
    at callback (/app/node_modules/@nestjs/core/injector/injector.js:42:41)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async Injector.resolveConstructorParams (/app/node_modules/@nestjs/core/injector/injector.js:114:24)
    at async Injector.loadInstance (/app/node_modules/@nestjs/core/injector/injector.js:46:9)
    at async Injector.loadProvider (/app/node_modules/@nestjs/core/injector/injector.js:68:9)
    at async Promise.all (index 4)

To Reproduce
Simply use MikroOrmModule.forRootAsync() in imports[] in Nestjs AppModule.
In my case I'm injecting ConfigService from Nestjs, but i don't think this should change something.

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [configuration]
    }),
    MikroOrmModule.forRootAsync({
      useFactory: (configService: ConfigService) => ({
        metadataProvider: TsMorphMetadataProvider,
        namingStrategy: EntityCaseNamingStrategy,
        entities: ["./dist/**/entities/*.entity.js"],
        entitiesTs: ["./src/**/entities/*.entity.ts"],
        type: "postgresql",
        dbName: configService.get("database.name"),
        host: configService.get("database.host"),
        port: configService.get("database.port"),
        user: configService.get("database.user"),
        password: configService.get("database.password")
      }),
      inject: [ConfigService]
    })
  ],
  controllers: [AppController],
  providers: [AppService, MikroORM]
})

Expected behavior
Get a MikroOrm instance with provided configuration.

Versions

Dependency Version
node 14
typescript 3.7.4
mikro-orm/core 4.3.4
mikro-orm/nestjs 4.2.0
mikro-orm/postgresql 4.3.4
mikro-orm/reflection 4.3.4
@SimoneDagna SimoneDagna added the bug Something isn't working label Jan 8, 2021
@B4nan
Copy link
Member

B4nan commented Jan 8, 2021

Having MikroORM explicitly inside providers seems wrong, try removing it.

@B4nan
Copy link
Member

B4nan commented Jan 8, 2021

You can see that from the stack trace, it is caused by that because nest di is trying to create new instance itself. Remove it and let the nest mikro orm adapter create the instance.

@B4nan B4nan closed this as completed Jan 8, 2021
@SimoneDagna
Copy link
Author

Awesome! Removing MikroOrm from providers solved the problem, thanks for the support.

@marcus-sa
Copy link

marcus-sa commented May 26, 2021

Still seems to be an issue.
Currently when instantiating using forRootAsync, it just causes the app to exit instantly, without any errors thrown at all.

You can find an example here https://github.com/marcus-sa/nest-convoy/blob/feat/mikro-orm/packages/messaging/broker/database/convoy-database.module.ts#L25

@B4nan
Copy link
Member

B4nan commented May 26, 2021

If you want help, provide a simple reproduction and all the details as described in issue template. Your linked project is too huge to review. But this particular issue was always invalid, if you see similar stack trace, it might point to some misusage rather than bug. Make sure you do not have MikroORM inside providers, it will be exported automatically. Also ensure you are calling forRootAsync only once (but that wouldn't probably cause this).

@Saegusae
Copy link

Saegusae commented Dec 19, 2022

I can still reproduce this issue with a similar setup, I dont have anything in providers/exports. Just trying to initialize with forRootAsync will cause the same error even when PostgreSQLDriver is explicitly provided. Worth mentioning this is a NestJS application running under Nx Framework.

Here's the file I'm initializing the root module from, this is called only once by the AppModule entry point:

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { MikroOrmModule } from '@mikro-orm/nestjs';

@Module({
  imports: [
    MikroOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        type: 'postgresql',
        dbName: configService.get<string>('DATABASE_NAME'),
        host: configService.get<string>('DATABASE_HOST'),
        port: configService.get<number>('DATABASE_PORT'),
        user: configService.get<string>('DATABASE_USER'),
        password: configService.get<string>('DATABASE_PASS'),
        entitiesTs: ['libs/entities/src/lib'],
        autoLoadEntities: true,
      }),
    }),
  ]
})
export class DatabaseModule {}

PS. Having the factory method async and return a promise yields the same result.

@JhonFuenzalida
Copy link

JhonFuenzalida commented Dec 20, 2022

I had the same error and I solved it by changing the type to drive

import { Module } from '@nestjs/common';
  import { ConfigModule, ConfigService } from '@nestjs/config';
  import { MikroOrmModule } from '@mikro-orm/nestjs';
  import { PostgreSqlDriver } from '@mikro-orm/postgresql';
  
  @Module({
    imports: [
      MikroOrmModule.forRootAsync({
        imports: [ConfigModule],
        inject: [ConfigService],
        useFactory: (configService: ConfigService) => ({
          driver: PostgreSqlDriver,
          dbName: configService.get<string>('DATABASE_NAME'),
          host: configService.get<string>('DATABASE_HOST'),
          port: configService.get<number>('DATABASE_PORT'),
          user: configService.get<string>('DATABASE_USER'),
          password: configService.get<string>('DATABASE_PASS'),
          entitiesTs: ['libs/entities/src/lib'],
          autoLoadEntities: true,
        }),
      }),
    ]
  })
  export class DatabaseModule {}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants