[ ] Regression
[ ] Bug report
[ ] Feature request
[x] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
DynamicModule aren't singleton
DynamicModules should be singletons
import {Module} from "@nestjs/common";
@Module({
imports: [ModuleC.ForRoot("A")],
controllers: [],
providers: [],
exports: [],
})
export class ModuleA {}
import {Module} from "@nestjs/common";
@Module({
imports: [ModuleC.ForRoot("B")],
controllers: [],
providers: [],
exports: [],
})
export class ModuleB {}
import {Module} from "@nestjs/common";
@Module({
imports: [],
controllers: [],
providers: [],
exports: [],
})
export class ModuleC {
private static _Inc: number = 0;
private static _Entities: string[] = [];
public constructor() {
this._test = ModuleC._Inc;
ModuleC._Inc ++;
}
public static ForRoot(...entities: string[]): void {
ModuleC._Entities = ModuleC._Entities.concat(entities);
return {
module: ModuleC
providers: // createProviders somewhere using our entities
}
}
public onModuleInit(): any {
console.log(this._test);
console.log(ModuleC._Entities);
}
}
will output
[ 'A', 'B' ]
0
[ 'A', 'B' ]
I would like to have
['A', 'B']
==================================
The workaround I found is the following
import {Module} from "@nestjs/common";
ModuleC.Configure("A");
@Module({
imports: [ModuleC],
controllers: [],
providers: [],
exports: [],
})
export class ModuleA {}
import {Module} from "@nestjs/common";
ModuleC.Configure("B");
@Module({
imports: [ModuleC],
controllers: [],
providers: [],
exports: [],
})
export class ModuleB {}
import {Module} from "@nestjs/common";
@Module({
imports: [],
controllers: [],
providers: [],
exports: [],
})
export class ModuleC {
private static _Inc: number = 0;
private static _Entities: string[] = [];
public constructor() {
this._test = ModuleC._Inc;
ModuleC._Inc ++;
}
public static Configure(...entities: string[]): void {
ModuleC._Entities = ModuleC._Entities.concat(entities);
}
public onModuleInit(): any {
console.log(this._test);
console.log(ModuleC._Entities);
}
}
which output
[ 'A', 'B' ]
but the obvious is that I can't export any of my dynamically created providers.
I am creating a DatabaseModule where I want typeorm to know about all the entities that my project will have before creating it.
Nest version: 5.3.2
For Tooling issues:
- Node version: 10
- Platform: Mac
Quite new to NestJS so I might have missed the obvious.
Thanks!
I am creating a DatabaseModule where I want typeorm to know about all the entities that my project will have before creating it.
I would suggest using another module which is shared across all dynamic modules. You could take a look at @nestjs/typeorm source code to get some inspiration how it might work underneath 馃檪 https://github.com/nestjs/typeorm
In terms of the real topic of this issue, dynamic modules with different configurations AREN'T singletons and they cannot be singletons. It doesn't make too much sense honestly.
Also you aren't be able to cache async dynamic modules, as you can't identify the context of the method to get the class without running it to get the dynamic metadata which will create the module token for identification.
It would be possible to not having to run the module compiler in the same scope over and over, if you just look into the index of the imported module instead of "compiling" it to get the dynamic metadata to generate the token more than once.
@kamilmysliwiec the TypeOrmCoreModule and TypeOrmModule ?
As for the singleton why is so?
The config is used to create providers, etc but the module itself is the same
{
module: ModuleC
}
I am still wondering why they can't be singleton except if I missed something.
Another question is can you provide already an instance to the module property (instead of having it instanciated by Nest underlying DI?
Still new to Nest so pardon my silly questions :)
@marcus-sa would you have a lead implementation wise?
@kamilmysliwiec the delegation works good :+1:
For whoever coming here
Module A
import {Module} from "@nestjs/common";
@Module({
imports: [ModuleC.ForRootAsync("A")],
controllers: [],
providers: [],
exports: [],
})
export class ModuleA {}
Module B
import {Module} from "@nestjs/common";
@Module({
imports: [ModuleC.ForRootAsync("B")],
controllers: [],
providers: [],
exports: [],
})
export class ModuleB {}
Module C
import {Module} from "@nestjs/common";
@Module({
imports: [],
controllers: [],
providers: [],
exports: [],
})
export class ModuleC {
public static ForRootAsync(...entities: string[]): DynamicModule {
return {
module: ModuleC,
imports: [ModuleCCore.ForRootAsync(...entities)],
};
}
}
Module C Core
import {Module} from "@nestjs/common";
@Module({
imports: [],
controllers: [],
providers: [],
exports: [],
})
export class ModuleCCore {
private static _Inc: number = 0;
private static _Entities: string[] = [];
public constructor() {
this._test = ModuleC._Inc;
ModuleC._Inc ++;
}
public static ForRoot(...entities: string[]): void {
ModuleCCore._Entities = ModuleCCore._Entities.concat(entities);
return {
module: ModuleCCore
providers: // createProviders somewhere using our entities
}
}
public onModuleInit(): any {
console.log(this._test);
console.log(ModuleCCore._Entities);
}
}
and the output is then
[ 'A', 'B' ]
馃帀
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.
Most helpful comment
@kamilmysliwiec the delegation works good :+1:
For whoever coming here
Module A
Module B
Module C
Module C Core
and the output is then
馃帀