I am creating an EventPublisher that must take 3 dependencies in the constructor
@Injectable()
export class EventStorePublisher implements IEventPublisher {
constructor(private readonly eventStore: IEventStore,
@Inject('STREAM_NAME_PUBLISHER') private readonly category: string,
@Inject('ID_ATTRIBUTE_NAME_PUBLISHER') private readonly idName: string) {
}
}
This way I want to customize the publishing.
It is a part of a util module that does not know at the moment which string inject inside:
@Global()
@Module({
providers: [
{
provide: IEventStore,
useClass: EventStore,
},
//...
],
exports: [
{
provide: IEventStore,
useClass: EventStore,
},
//...
],
})
export class EventStoreModule {
//...
static forFeature(): DynamicModule {
return {
module: EventStoreModule,
providers: [
EventStorePublisher,
{
provide: "STREAM_NAME_PUBLISHER",
useValue: null
},
{
provide: "ID_ATTRIBUTE_NAME_PUBLISHER",
useValue: null
},
],
exports: [
EventStorePublisher,
{
provide: "STREAM_NAME_PUBLISHER",
useValue: null
},
{
provide: "ID_ATTRIBUTE_NAME_PUBLISHER",
useValue: null
},
],
};
}
}
I didn't find any other way to prevent NestJS to throw error about missing definitions for the tokens STREAM_NAME_PUBLISHER
or ID_ATTRIBUTE_NAME_PUBLISHER
. I am forced to provide them and to export them, otherwise the module does not work.
When it comes to a Module that needs to customize the category and the idName :
@Module({
imports: [
CqrsModule,
EventStoreModule.forFeature(),
EventStorePublisher,
],
providers: [
//...
{
provide: "STREAM_NAME_PUBLISHER",
useValue: "person"
},
{
provide: "ID_ATTRIBUTE_NAME_PUBLISHER",
useValue: "personId"
},
{
provide: EventStorePublisher,
useFactory: (eventStore:IEventStore,category: string, id: string) => new EventStorePublisher(eventStore, category,id),
inject: [IEventStore, "STREAM_NAME_PUBLISHER", "ID_ATTRIBUTE_NAME_PUBLISHER"]
},
],
controllers: [
//...
],
})
export class PersonModule implements OnModuleInit {
//...
}
Is there any way to avoid the predeclaration of with null
in the EventStoreModule ?
I want these tokens to be always overriden for each module using this EventStoreModule and the idea I come up with seems very very very ugly.
I've implemented something kind of similar to this, but overall, it's definitely pretty messy to do. For my code, I ended up implementing a NoopService
kind of approach, where the code is as minimal as possible and does nothing but let things pass through. All of my providers that were to be overwritten were initialized with
{
provide: ProviderName,
useClass: NoopService,
}
So that I could just let the providers properly initalise without worrying about any code running through them. This also lead to needing a lot of checks around the code as I wouldn't want these NoopService
s actually doing anything. If you want to check it out the codebase is here, specifically in the ogma-core.module.ts
, ogma.providers.ts
, and interceptor/ogma.intereptor.ts
files (along with those you can follow from there).