NestJS module import not working in the forRootAsync and forRootMethod of a dynamic module

1.5k views Asked by At

When trying to import another module inside of my dynamic modules nest throws the following error when using a service exported by that module inside of my services:

Error: Nest can't resolve dependencies of the ActivationService (UsersService, ?, USERS_MODULE_OPTIONS, MailService). Please make sure that the argument JwtService at index [1] is available in the UsersModule context.

When importing the Module with static configuration inside the @Module decorator everything works fine.

/** UsersModule */
@Global()
@Module({
  imports: [
    MikroOrmModule.forFeature([UserEntity]),
    JwtModule.register({
      secret: 'secret',
    }),
  ],
  providers: [UsersService, ActivationService, PasswordResetService],
  exports: [UsersService],
  controllers: [
    MyUserController,
    UsersController,
    ActivationController,
    PasswordResetController,
  ],
})
export class UsersModule {
  /**
   * Creates UsersModule asynchronously
   * @param options
   */
  public static forRootAsync(
    options: AsyncModuleOptions<UsersModuleOptions>,
  ): DynamicModule {
    return {
      module: UsersModule,
      imports: [...(options.imports || [])],
      providers: createAsyncModuleOptionsProviders(
        options,
        USERS_MODULE_OPTIONS,
      ),
      exports: [USERS_MODULE_OPTIONS],
    };
  }
}

By importing the JwtModule inside of the forRootAsync method of my dynamic module im getting the error above.

/** UsersModule */
@Global()
@Module({
  imports: [MikroOrmModule.forFeature([UserEntity])],
  providers: [UsersService, ActivationService, PasswordResetService],
  exports: [UsersService],
  controllers: [
    MyUserController,
    UsersController,
    ActivationController,
    PasswordResetController,
  ],
})
export class UsersModule {
  /**
   * Creates UsersModule asynchronously
   * @param options
   */
  public static forRootAsync(
    options: AsyncModuleOptions<UsersModuleOptions>,
  ): DynamicModule {
    return {
      module: UsersModule,
      imports: [
        JwtModule.registerAsync({
          inject: [USERS_MODULE_OPTIONS],
          useFactory: async (options: UsersModuleOptions) => ({
            secret: options.secret,
            privateKey: options.privateKey,
            publicKey: options.publicKey,
          }),
        }),
        ...(options.imports || []),
      ],
      providers: createAsyncModuleOptionsProviders(
        options,
        USERS_MODULE_OPTIONS,
      ),
      exports: [USERS_MODULE_OPTIONS],
    };
  }
}

I have already used this kind of configuration successfully in another module without obtaining the error:

/** JwtAuthenticationModule */
@Global()
@Module({
  imports: [PassportModule],
  providers: [
    JwtAuthenticationService,
    JwtStrategy,
    {
      provide: APP_GUARD,
      useClass: JwtAuthenticationGuard,
    },
  ],
  exports: [JwtAuthenticationService],
  controllers: [JwtAuthenticationController],
})
export class JwtAuthenticationModule {
  /**
   * Creates JwtAuthenticationModule asynchronously
   * @param options
   */
  public static forRootAsync(
    options: AsyncModuleOptions<JwtAuthenticationModuleOptions>,
  ): DynamicModule {
    return {
      module: JwtAuthenticationModule,
      imports: [
        JwtModule.registerAsync({
          inject: [JWT_AUTHENTICATION_MODULE_OPTIONS],
          useFactory: async (options: JwtAuthenticationModuleOptions) => ({
            secret: options.secret,
            privateKey: options.privateKey,
            publicKey: options.publicKey,
          }),
        }),
        ...(options.imports || []),
      ],
      providers: [
        this.getUsersServiceProvider(),
        ...createAsyncModuleOptionsProviders(
          options,
          JWT_AUTHENTICATION_MODULE_OPTIONS,
        ),
      ],
      exports: [JWT_AUTHENTICATION_MODULE_OPTIONS],
    };
  }

  /**
   * Fetches UsersServiceProvider from options
   * @private
   */
  private static getUsersServiceProvider(): Provider<UsersServiceContract> {
    return {
      inject: [JWT_AUTHENTICATION_MODULE_OPTIONS],
      provide: USERS_SERVICE,
      useFactory: (options: JwtAuthenticationModuleOptions) =>
        options.usersService,
    };
  }
}

Importing the JwtModule with a static secret inside of the forRootAsync method also throws the same error.


/** UsersModule */
@Global()
@Module({
  imports: [MikroOrmModule.forFeature([UserEntity])],
  providers: [UsersService, ActivationService, PasswordResetService],
  exports: [UsersService],
  controllers: [
    MyUserController,
    UsersController,
    ActivationController,
    PasswordResetController,
  ],
})
export class UsersModule {
  /**
   * Creates UsersModule asynchronously
   * @param options
   */
  public static forRootAsync(
    options: AsyncModuleOptions<UsersModuleOptions>,
  ): DynamicModule {
    return {
      module: UsersModule,
      imports: [
        JwtModule.register({
          secret: 'secret',
        }),
        ...(options.imports || []),
      ],
      providers: createAsyncModuleOptionsProviders(
        options,
        USERS_MODULE_OPTIONS,
      ),
      exports: [USERS_MODULE_OPTIONS],
    };
  }
}

1

There are 1 answers

1
ardritkrasniqi On

Try to import the AuthModule on the UsersModule