Hello again,
I came across a problem where I am not sure if this is a wanted behavior regarding the injection via a factory.
I have the following module configuration:
Problem Case
@Module({
components: [
UserModelFactory,
{
provide: 'UserModel',
useFactory: (userModelFactory: UserModelFactory) => {
return userModelFactory.getSingletonInstance();
},
inject: [UserModelFactory],
},
],
})
export class MongooseModelsModule {
}
In my repository layer I want to inject the mongoose model created by the factory class:
export class UserRepository implements IUserRepository {
private readonly user: mongoose.Model<UserDocument>;
constructor(
@Inject('UserModel') user: mongoose.Model<UserDocument>,
) {
this.user = user;
}
}
Still I get an error message that the dependency of my repository class could not be resolved. My factory class itself is called and the model is created right.
I debugged the code and came to the following line where the problem is coming up:
scanForComponentInRelatedModules(module, name) {
const relatedModules = module.relatedModules || [];
let component = null;
relatedModules.forEach((relatedModule) => {
const { components, exports } = relatedModule;
// Coponents contains 'UserModel' but exports doesn't resulting in returning null
if (!exports.has(name) || !components.has(name))
return;
component = components.get(name);
if (!component.isResolved) {
this.loadInstanceOfComponent(component, relatedModule);
}
});
return component;
}
Is it really necessary that the 'UserModel' must be within the exports metadata as I only define the component for the injection (see module above). This behavior seems strange to me.
Solution / Workaround
Doing the following Module configuration I get a working result:
@Module({
exports: {
UserModelFactory,
},
components: [
UserModelFactory,
{
provide: 'UserModelFactory',
useFactory: (userModelFactory: UserModelFactory) => {
return userModelFactory.getSingletonInstance();
},
inject: [UserModelFactory],
},
],
})
export class MongooseModelsModule {
}
export class UserRepository implements IUserRepository {
private readonly user: mongoose.Model<UserDocument>;
constructor(
@Inject('UserModelFactory') user: mongoose.Model<UserDocument>,
) {
this.user = user;
}
}
This seems a bit awkward to me as I have to name my key the same as the class constructor AND I have to put the constructor into components and exports. Is this behavior intended?