Nest: Support for DynamicModule in NestFactory.create

Created on 13 May 2018  路  15Comments  路  Source: nestjs/nest

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

DynamicModule are not supported by NestFactory create method.

Expected behavior

Support DynamicModule in NestFactory.create

What is the motivation / use case for changing the behavior?

I want to pass a configuration object to my application module and provide it there. I load it in the bootstrap method to get the port from the configuration.

Environment


Nest version: 5.0.0-rc.4

core done 馃憦 type

Most helpful comment

5.2.0 is here!

All 15 comments

Could you share your code please ?

@adrien2p Well, this is related to https://github.com/nestjs/typeorm/issues/24. There is an example there without the config part. Provider only seems to work, but nested dynamic module throw an exception when trying to inject services from them. I looked a bit and the dependency injection wrapper had undefined entries.

Humm i see :)

I have this issue as well and played around with it for what will make the following error appear:

[Nest] 5877   - 2018-7-6 16:55:02   [ExceptionHandler] Cannot destructure property `relatedModules` of 'undefined' or 'null'.
TypeError: Cannot destructure property `relatedModules` of 'undefined' or 'null'.
    at flatten (/home/y0hy0h/WebstormProjects/nest-typeorm/node_modules/@nestjs/core/injector/injector.js:161:49)
    at Array.map (<anonymous>)
    at Injector.flatMap (/home/y0hy0h/WebstormProjects/nest-typeorm/node_modules/@nestjs/core/injector/injector.js:169:54)
    at Injector.lookupComponentInRelatedModules (/home/y0hy0h/WebstormProjects/nest-typeorm/node_modules/@nestjs/core/injector/injector.js:136:42)
    at Injector.lookupComponentInExports (/home/y0hy0h/WebstormProjects/nest-typeorm/node_modules/@nestjs/core/injector/injector.js:127:44)
    at scanInExports (/home/y0hy0h/WebstormProjects/nest-typeorm/node_modules/@nestjs/core/injector/injector.js:123:42)
    at Injector.lookupComponent (/home/y0hy0h/WebstormProjects/nest-typeorm/node_modules/@nestjs/core/injector/injector.js:124:68)
    at Injector.resolveComponentInstance (/home/y0hy0h/WebstormProjects/nest-typeorm/node_modules/@nestjs/core/injector/injector.js:113:44)
    at Injector.resolveSingleParam (/home/y0hy0h/WebstormProjects/nest-typeorm/node_modules/@nestjs/core/injector/injector.js:102:27)
    at Promise.all.args.map (/home/y0hy0h/WebstormProjects/nest-typeorm/node_modules/@nestjs/core/injector/injector.js:80:45)
 1: node::Abort() [/home/y0hy0h/.nvm/versions/node/v8.11.1/bin/node]
 2: 0x11e8359 [/home/y0hy0h/.nvm/versions/node/v8.11.1/bin/node]
 3: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) [/home/y0hy0h/.nvm/versions/node/v8.11.1/bin/node]
 4: 0xb7a9ac [/home/y0hy0h/.nvm/versions/node/v8.11.1/bin/node]
 5: v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [/home/y0hy0h/.nvm/versions/node/v8.11.1/bin/node]
 6: 0x152434f042fd
[nodemon] app crashed - waiting for file changes before starting...
Aborted (core dumped)

Repro

I've created a repro repo based on the CLI scaffold.

To see the error, just run yarn start:dev.

Basic Setup

What is needed for this error to occur is a dependency between modules, as well as passing a dynamic module to NestFactory.create().

So I created the DependentModule with a service that depends on the LibraryService. Additionally, I loaded DependentModule dynamically inside AppModule.dynamic(), which generates the dynamic module that is finally passed to NestFactory.create().

Observation

First I thought that the import in DependentModule is causing the error. However, it is enough to specify the dependency in the constructor of DependentService (I've added a TODO comment to help you find it). If you (un)comment that import, you control whether the app crashes. (Note that when commented out, the dependency is missing and the app will crash later, namely when the route is invoked.)

Of course, you can also make this work by removing the dynamic module and importing DependentModule statically.

Hey !
First, you should import the LibraryModule into your AppModule

@Module({
  providers: [
    AppService,
  ],
  controllers: [
    AppController,
  ],
})
export class AppModule {
  static dynamic(): DynamicModule {
    return {
      module: AppModule,
      imports: [
        LibraryModule,
        DependentModule,
      ],
    };
  }
}

@adrien2p It's imported directly in DependentModule. I can make this setup work by simply commenting out one line.

Yes, if you comment this line that works because you don't use any thing else from the LibraryModule. But, you have to register all your modules into the main module before to be able to use it anywhere else

your issue is not related to this one Support for DynamicModule in NestFactory.create

@adrien2p The only thing I have changed in this branch is that instead of using a dynamic module in NestFactory.create(), I declare the imports statically as usual. And the statically imported works fine, even without the change you proposed.

So as far as I can see, my issue is that NestFactory.create() is not working properly with dynamic modules. Did I miss something? :thinking:

humm, Yes you right i didn't notice that ^^

Okay, i think that i know where the problem come from

The method scanner#scanForModules get the related module from the metadata and then call recursively the method on all imported modules. The fact is that the dynamicModule AppModule doesn't have any metadata key when it is dynamic @kamilmysliwiec did you notice that ?
but if both modules are dynamic, that works ...

I'm getting the same error when I upgraded from Nest 4.x.x to 5.x.x. Whats the state of this? Is this going to be fixed or is there another way? Angular Universal also does not support dynamic modules while bootstrapping but it provides a way to add providers while bootstrapping:

app.engine('html', ngExpressEngine({
    bootstrap: AppServerModuleNgFactory,
    providers: [
        { provide: SOME_TOKEN, useValue: process.env.THING_YOU_CARE_ABOUT },
    ]
}));

With Nest I could imagine something like this:

await NestFactory.create(AppModule, { 
    providers: [
        { provide: SOME_TOKEN, useValue: process.env.THING_YOU_CARE_ABOUT },
    ]
});

Do not care whether dynamic modules are supported or the angular universal approach (prefer dynamic module though).

Because of this error I am not able to upgrade to 5.x.x which is really unfortunate...

That is not yet supported.

5.2.0 is here!

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings