Nestjs modules - shared custom provider is not working - nestjs

I have a proyect with multiple modules, and all of them need the same provider, then I have used a shared module but I don't know where the mistake is
import { Module } from '#nestjs/common';
import { ChatBot } from './chat-bot';
import { ChatBotImplementation } from './chat-bot.implementation';
#Module({
providers: [{ provide: ChatBot, useClass: ChatBotImplementation }],
exports: [ChatBot],
})
export class SharedModule {}
import { Module } from '#nestjs/common';
import { CoreService } from './core.service';
#Module({
providers: [CoreService],
})
export class CoreModule {}
import { Module } from '#nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { SharedModule } from './shared/shared.module';
import { CoreModule } from './core/core.module';
#Module({
imports: [SharedModule, CoreModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
import { Injectable } from '#nestjs/common';
import { ChatBot } from 'src/shared/chat-bot';
#Injectable()
export class CoreService {
constructor(chatBot: ChatBot) {
chatBot.send('hola');
}
}
When I start the server, it throws this error:
[Nest] 8456 - 29/12/2022, 17:21:08 ERROR [ExceptionHandler] Nest can't resolve dependencies of the CoreService (?). Please make sure that the argument ChatBot at index [0] is available in the CoreModule context.
Potential solutions:
- Is CoreModule a valid NestJS module?
- If ChatBot is a provider, is it part of the current CoreModule?
- If ChatBot is exported from a separate #Module, is that module imported within CoreModule?
#Module({
imports: [ /* the Module containing ChatBot */ ]
})
ChatBot is an abstract class and ChatBotImplementation implements ChatBot abstract class, I have tried with symbol as provide but it don't working either. If I put the provider in the same module that use it then it works, I supose that the misteka should be in the, exports part?

Your CoreModule doesn't have the SharedModule in its imports so it doesn't have access to providers from the SharedModule's exports. Add imports: [SharedModule] to the CoreModule's module metadata and you'll be good to go

Related

How do I rename mongoose connections in NestJs

I am having trouble giving a mongoose database connection a name (so that I can use more than one).
I have separated my database config out into a separate module so that I can import it easily when testing e2e.
My Database Module looks like:
import { Module } from "#nestjs/common";
import { MongooseModule } from "#nestjs/mongoose";
import { DatabaseService } from "./database.service";
#Module({
imports: [
MongooseModule.forRootAsync({
//connectionName: 'database',
useFactory: () => ({ uri: `mongodb://mongoUri` }),
}),
],
providers: [DatabaseService],
exports: [DatabaseService]
})
export class DatabaseModule { };
and my Database Service is:
import { Injectable } from "#nestjs/common";
import { InjectConnection } from "#nestjs/mongoose";
import { Connection } from 'mongoose';
#Injectable()
export class DatabaseService {
constructor(#InjectConnection() private readonly connection: Connection) {}
getDbHandle(): Connection {
return this.connection
}
}
with App Module:
import { Module, NestModule } from '#nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MyModule } from './my/my.module';
import { DatabaseModule } from './common/database/database.module';
#Module({
imports: [
MyModule,
DatabaseModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {}
and My Module:
import { Module } from '#nestjs/common';
import { MyService } from '../services/my.service';
import { MyController } from '../controllers/my.controller';
import { MongooseModule } from '#nestjs/mongoose';
import { My } from '../models/my.schema';
#Module({
imports: [
MongooseModule.forFeature([{ name: My.name, schema: MySchema }]) //, 'database'),
],
controllers: [MyController],
providers: [MyService]
})
export class MyModule {}
This all works fine, however if I uncomment the comments (i.e. add a connection name in Database Module and to the import in My Module, I get the error: Nest can't resolve dependencies of the DatabaseService (?). Please make sure that the argument DatabaseConnection at index [0] is available in the DatabaseModule context.
What is it that adding a connection name does to cause this error? And how can I resolve it? Any help greatly appreciated.
Because #InjectConnection() takes an optional parameter which is the name, otherwise some "default" connection will be used.
See the source code here:
export const InjectConnection = (name?: string) =>
Inject(getConnectionToken(name));
https://github.com/nestjs/mongoose/blob/master/lib/common/mongoose.decorators.ts

Nest can't resolve dependencies of the ~repository

I'm getting a strange error with my nestjs code.
Repository not connected in module file
[ExceptionHandler] Nest can't resolve dependencies of the UserRepository (?). Please make sure that the argument Connection at index [0] is available in the TypeOrmModule context
The current code is this
app.module.ts
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import connectionOptions from 'ormconfig';
import { UserModule } from './modules';
#Module({
imports: [TypeOrmModule.forRoot(connectionOptions), UserModule],
providers: [],
})
export class AppModule {}
user.module.ts
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import { UserRepository } from 'src/repositories';
import { UserController } from './user.controller';
import { UserService } from './user.service';
#Module({
imports: [TypeOrmModule.forFeature([UserRepository])],
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
user.repository.ts
import { User } from '../entities';
import { EntityRepository, Repository } from 'typeorm';
#EntityRepository(User)
export class UserRepository extends Repository<User> {
async findOneById(userId: string) {
return await this.createQueryBuilder()
.where('user_id = :userId', {
userId,
})
.getOne();
}
}
How can I fix it?
From the code you provided, there should be no problem. The only thing that will trigger the error is the ormconfig config you did not provide.
Can you check if you have name: "xxxx" in your ormconfig config like below:
{
name: 'dbname', <-- check if you have name config here
type: 'mysql',
host: 'localhost',
port: 3306,
...
}
There are 2 ways to solve it if you have name in the config:
If there is only ONE database, you can remove the name and use the default name typeorm provides.
If you have multiple databases or you want to preserve the connection name, you will need to specify the name in the code as well to help typeorm to determine which database to work with, see the below changes:
user.module.ts
#Module({
imports: [
TypeOrmModule.forFeature([UserRepository], 'dbname'), // provide the name here
],
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
user.service.ts
#Injectable()
export class UserService {
constructor(
#InjectRepository(UserRepository, 'dbname') // provide the name here
private usersRepository: UserRepository,
) {}
...
}

NestJS cannot resolve my UsersService dependency why? Is it due to UserModel?

I am trying to learn NodeJS framework. I have initialized a project for that and now I am trying to add authentication to secure the HTTP access. I follows the NestJS documentation but I have the following error when I inject my UsersService in the AuthService:
[Nest] 14876 - 13/04/2020 à 09:26:19 [ExceptionHandler] Nest can't resolve dependencies of the UsersService (?). Please make sure that the argument UserModel at index [0] is available in the AuthModule context.
Potential solutions:
- If UserModel is a provider, is it part of the current AuthModule?
- If UserModel is exported from a separate #Module, is that module imported within AuthModule?
#Module({
imports: [ /* the Module containing UserModel */ ]
})
+2ms
Error: Nest can't resolve dependencies of the UsersService (?). Please make sure that the argument UserModel at index [0] is available in the AuthModule context.
It seems that it is due to the following injection in my UsersService :
constructor(#InjectModel('User') private readonly UserModel: Model) {}
but I doesn't know how to solve this problem. My training project is stored on github :
https://github.com/afontange/nest-js.git
I read other tickets on same subject but I don't know what is the solution for my problem.
Thanks for your help.
export const UsersSchema = new Schema({
name: String,
});
Module({
imports: [
MongooseModule.forFeature([{ name: 'Users', schema: UsersSchema }]) // add
],
controllers: [],
providers: [],
exports: []
})
export class AuthModule {}
Do you add in your Auth.module.ts
The AuthModule is the following:
import { Module } from '#nestjs/common';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';
import { PassportModule } from '#nestjs/passport';
import { LocalStrategy } from './local.strategy';
import { UsersService } from '../users/users.service';
#Module({
imports: [UsersModule, PassportModule],
providers: [AuthService, LocalStrategy, UsersService],
})
export class AuthModule {}

Mock multiple TypeORM repositories in NestJS

I'm having trouble to mock multiple repositories from different modules in NestJS.
I'm using a UsersRepository from a UsersModule inside another module service (NotesService). The code is working fine, but I can't make the unit tests work.
I have the following error: Error: Nest can't resolve dependencies of the UserRepository (?). Please make sure that the argument Connection at index [0] is available in the TypeOrmModule context.
Minimal reproduction
// [users.module.ts]
#Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}
// [users.service.ts]
#Injectable()
export class UsersService {
constructor(#InjectRepository(User) private usersRepository: UsersRepository) {}
...
}
// [notes.module.ts]
#Module({
imports: [
TypeOrmModule.forFeature([Note, User]),
UsersModule,
],
controllers: [NotesController],
providers: [NotesService],
})
export class NotesModule {
}
// [notes.service.ts]
#Injectable()
export class NotesService {
constructor(
#InjectRepository(Note) private notesRepository: NotesRepository,
#InjectRepository(User) private usersRepository: UsersRepository,
) {}
...
}
Here is my unit test configuration:
// [notes.service.spec.ts]
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [UsersModule],
providers: [
NotesService,
{ provide: getRepositoryToken(Note), useFactory: repositoryMockFactory },
{ provide: getRepositoryToken(User), useFactory: repositoryMockFactory },
],
}).compile();
notesService = module.get<NotesService>(NotesService);
notesRepositoryMock = module.get(getRepositoryToken(Note));
});
The problem is I can't make a proper mock of the UsersRepository that comes from another module.
I tried importing TypeOrmModule directly inside the test, and everything I could but I can't make it work.
You don't need to import the UsersModule if you are directly providing the NotesService and the mocks that it will depend on. The reason for the error is that Nest is trying to resolve TypeormModule.forFeature([User]) from the UsersModule. Simply remove the import in the test and you should be golden.

How do I import a global provider into another global provider in NestJS?

I want to import the config provider from the documentation into another provider.
I am using the same config structure that is sown in the documentation here.
So the config.module.ts looks like this:
import { Module, Global } from '#nestjs/common';
import { ConfigService } from './config.service';
#Global()
#Module({
providers: [
{
provide: ConfigService,
useValue: new ConfigService(
`config/env/${process.env.NODE_ENV || 'development'}.env`,
),
},
],
exports: [ConfigService],
})
export class ConfigModule {}
And the other provider should look something like this correct?
token.module.ts
import { Module, Global } from '#nestjs/common';
import { TokenService} from './token.service';
import { ConfigService } from './config.service';
#Global()
#Module({
import: [ConfigService]
providers: [TokenService],
exports: [TokenService],
})
export class TokenModule {}
While the TokenService should look something like this
token.service.ts
import { ConfigService } from '../../config/config.service';
export class TokenService {
constructor(private readonly configService: ConfigService) {}
test(): string {
return this.configService.get('TestVal');
}
}
But when I import TokenModule in AppModule I get this error The "path" argument must be one of type string, Buffer, or URL. Received type undefined
You forgot to mark your TokenService as #Injectable(). You need to tell NestJS about arguments that need to be provided to other services.

Resources