Reputation: 12418
I have a NestJS application consisting of modules, each with its own services, controllers, and entities.
Why do I need to import all the required entities directly from various modules into other modules, rather than just importing the corresponding module? Am I doing something wrong, or is this a feature of NestJS that I don't fully understand?
Let's say, I have a MetaData-module consisting of:
and an Image-Module that shall import the MetaData-Module with its entities and service:
metadata.module.ts:
@Module({
imports: [TypeOrmModule.forFeature([MetaDataEntity])],
providers: [MetadataService],
controllers: [MetadataController],
exports: [MetadataService],
})
export class MetadataModule {}
metadata.entity.ts:
@Entity({ name: 'metadata' })
@Unique('idx_unique_uuid', ['uuid'])
export class MetaDataEntity extends ImmutableBaseEntity {
@Column({ name: 'uuid', type: 'varchar', length: 64 })
@IsUUID()
@IsNotEmpty()
uuid: string;
/// many others properties as well
}
metadata.service.ts:
export class MetadataService {
constructor(
private configService: ConfigService,
@InjectRepository(MetaDataEntity) private readonly repository: Repository<MetaDataEntity>,
) {}
// functions...
}
image.module.ts:
@Module({
imports: [MetadataModule, HttpModule],
providers: [ImagesService],
controllers: [ImagesController],
})
export class ImagesModule {}
image.service.ts:
@Injectable()
export class ImagesService {
constructor(
private configService: ConfigService,
@InjectRepository(MetaDataEntity) private readonly repository: Repository<MetaDataEntity>,
) {}
This can't get compiled thanks to the following error:
ERROR [ExceptionHandler] Nest can't resolve dependencies of the ImagesService (ConfigService, HttpService, ?). Please make sure that the argument MetaDataEntityRepository at index [2] is available in the ImagesModule context.
In order to fix this issue, I had to import the MetaData-Entity into the Image-Module:
@Module({
imports: [TypeOrmModule.forFeature([MetaDataEntity]), HttpModule],
providers: [ImagesService, TypeOrmModule],
controllers: [ImagesController],
})
export class ImagesModule {}
The issue is, that on all other Modules where I want to import MetaDataEntity, I have to import it with TypeOrmModule.forFeature([MetaDataEntity]
.
Even in other Modules, that are importing the ImageModule, I need to import the MetaDataEntity separately.
At this point, I'm curious what the purpose of a Module is in NestJS. According to the official docs at https://docs.nestjs.com/modules I understood it like importing a Module should provide all parts of the module for the importing module. But that's not the case.
Upvotes: 1
Views: 632
Reputation: 70490
This is how providers in NestJS work. What TypeOrmModule.forFeature([Entity])
is doing under the hood is creating an injection token for "EntityRepository"
in the context of the current module. It'd be just like making your own custom provider:
{
provide: "EntityRepository",
inject: [getConnectionToken()],
useFactory: (connection: TypeOrmConnection) => connection.getRepository(Entity)
}
To expose this provider to other modules from this module, you would normally need to add the injection token to the module's exports
array. However, when you have a module like this, you might not know what the injection token is, so what you can do instead is make use of something called module re-exporting. In this case, you have TypeOrmModule.forFeature()
in the imports
array, and add TypeOrmModule
to the exports
array. This will expose the "EntityRepository"
token to other modules that import this module, and make things work the way you want to.
Upvotes: 1