I was using a plain mongo client in my event sourcing library beforehand and am adding support for schema validation to it using mongoose. Been scouring online as well as looking in the common errors page which seems to have a template that directly fits this error, except it's not being very specific as to where the problem is exactly.
I have been struggling to get the hang of the dependency injection for async dependencies.
Error: Nest can't resolve dependencies of the MongooseCoreModule (MongooseConnectionName, ?). Please make sure that the argument ModuleRef at index [1] is available in the MongooseCoreModule context.
I've stripped down everything to essentially the bare minimum basics to try and debug it. Here is my AppModule:
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true, envFilePath: '.env' }),
EventSourcingModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService): Promise<any> => {
return {
eventStoreConfig: {
uri: configService.get('EVENT_STORE_MONGO_URI'),
dbName: configService.get('EVENT_MONGO_DB_NAME'),
token: 'test-eventstore-token',
},
};
},
}),
],
})
export class AppModule {
}
And here is my event sourcing module:
@Global()
@Module({})
export class EventSourcingModule {
static registerAsync(
config: {
imports: Array<Type<any> | ForwardReference | DynamicModule>;
useFactory: (...args: any[]) => Promise<EventSourcingModuleConfig> | EventSourcingModuleConfig;
inject?: any[];
},
eventStoreToken: string = undefined
): DynamicModule {
return {
module: EventSourcingModule,
imports: [
...config.imports,
MongooseModule.forRootAsync({
connectionName: `${eventStoreToken}eventstoreCounterConnection`,
useFactory: async (eventSourcingConfig: EventSourcingModuleConfig) => {
return {
uri: eventSourcingConfig.eventStoreConfig.uri,
dbName: eventSourcingConfig.eventStoreConfig.dbName,
}
},
inject: ['EVENT_SOURCING_MODULE_OPTIONS'],
}),
MongooseModule.forFeatureAsync(
[{
name: 'counter',
useFactory: (): any => new mongoose.Schema({ _id: String, sequence_value: Number }, { collection: 'eventstore' }),
collection: 'eventstore',
}],
`${eventStoreToken}eventstoreCounterConnection`
),
],
providers: [
{
provide: 'EVENT_SOURCING_MODULE_OPTIONS',
useFactory: config.useFactory,
inject: config.inject,
},
{
provide: 'ENVIRONMENT_NAME',
useFactory: (config: EventSourcingModuleConfig) => {
return config && config.environmentName ? config.environmentName : '';
},
inject: ['EVENT_SOURCING_MODULE_OPTIONS'],
},
...this.createProvidersAsync(eventStoreToken),
ConfigService,
],
exports: [
...this.createExportsAsync(eventStoreToken),
],
};
}
private static createProvidersAsync(eventStoreToken: string) {
const providers = [];
providers.push({
provide: eventStoreToken ?? MongoEventStore,
useFactory: async (
config: EventSourcingModuleConfig,
connection: mongoose.Connection,
counterModel: Model<any>
) => {
if (config && config.eventStoreConfig)
return new MongoEventStore(connection, counterModel);
return null;
},
inject: ['EVENT_SOURCING_MODULE_OPTIONS', getConnectionToken()],
});
return providers;
}
private static createExportsAsync(eventStoreToken: string) {
return [eventStoreToken ?? MongoEventStore];
}
}