Getting below error while compiling the below code:
I am new to nestjs and this is the attached sample application code.
I tried replacing UsersService in module.ts with UsersModule as well but it didn't work. What am i doing wrong ?
[Nest] 19960 - 10/19/2020, 11:42:09 PM [NestFactory] Starting Nest application...
[Nest] 19960 - 10/19/2020, 11:42:09 PM [InstanceLoader] MongooseModule dependencies initialized +25ms
[Nest] 19960 - 10/19/2020, 11:42:09 PM [InstanceLoader] PassportModule dependencies initialized +1ms
[Nest] 19960 - 10/19/2020, 11:42:09 PM [ExceptionHandler] Nest can't resolve dependencies of the AuthService (?, JwtService). Please make sure that the argument UsersService at index [0] is available in the AuthService context.
Potential solutions:
If UsersService is a provider, is it part of the current AuthService?
If UsersService is exported from a separate #module, is that module imported within AuthService?
#module({
imports: [ /* the Module containing UsersService */ ]
})
Repoistory : https://github.com/richakhetan/task-manager-nest
You have a circular dependency between the AuthModule and UserModule and between the UserService and AuthService. To resolve this, on both the modules and the services you need to use a forwardRef. Generally, this would just look like
#Module({
imports: [forwardRef(() => UserModule)],
providers: [AuthService],
exports: [AuthService],
})
export class AuthModule {}
#Module({
imports: [forwardRef(() => AuthModule)],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}
#Injectable()
export class AuthService {
constructor(#Inject(forwardRef(() => UserService)) private readonly userService: UserService) {}
}
#Injectable()
export class UserService {
cosntructor(#Inject(forwardRef(() => AuthService) private readonly authService: AuthService) {}
}
Edit
Forgot to add the exports property
modules were not properly structured. I removed the code causing circular dependency from the modules and created a new module creating a clear structure.
Detailed Code can be found in the repository.
Repository : https://github.com/richakhetan/task-manager-nest
Related
I'm trying to setup a graphql nestjs clean architecture, I have my resolver call the service, service calls repository and repository calls orm methods. Am I missing a step?
But I get this error:
[Nest] 59764 - 03/10/2022, 16:36:13 ERROR [ExceptionHandler] Nest can't resolve dependencies of the AthleteRepository (?). Please make sure that the argument AthleteEntityRepository at index [0] is available in the GraphQLModule context.
Potential solutions:
- If AthleteEntityRepository is a provider, is it part of the current GraphQLModule?
- If AthleteEntityRepository is exported from a separate #Module, is that module imported within GraphQLModule?
#Module({
imports: [ /* the Module containing AthleteEntityRepository */ ]
})
Error: Nest can't resolve dependencies of the AthleteRepository (?). Please make sure that the argument AthleteEntityRepository at index [0] is available in the GraphQLModule context.
This is my module:
#Module({
imports: [
InfraestructureModule,
NestGraphqlModule.forRoot<MercuriusDriverConfig>({
driver: MercuriusDriver,
graphiql: true,
autoSchemaFile: join(
process.cwd(),
'src/infraestructure/graphql/schema.gql',
),
sortSchema: true,
}),
],
controllers: [AuthResolver, UserResolver],
providers: [
FirebaseService,
AthleteEntity,
AthleteRepository,
AthleteService,
],
})
export class GraphQLModule {}
Adding repository by comment request, it's mostly just wrappers around the typerom Repository.
import { Controller } from '#nestjs/common';
import { InjectRepository } from '#nestjs/typeorm';
import { Repository } from 'typeorm';
import { AthleteEntity } from '../entity/athlete.entity';
#Controller('')
export class AthleteRepository {
constructor(
#InjectRepository(AthleteEntity)
private athleteRepository: Repository<AthleteEntity>,
) {}
async getAthleteByUserId(id: string): Promise<AthleteEntity> {
return this.athleteRepository.findOne({ where: { id } });
}
async getAthletes(): Promise<AthleteEntity[]> {
return this.athleteRepository.find();
}
}
As you use #InjectRepository(AtheleteEntity) you need to have TypeOrmModule.forFeature([AtheleteEntity]) used in the imports of the GraphQlModule.
Side note: Is that supposed to be #Controller() or #Injectable()? It doesn't look like a standard HTTP or RPC controller to me
change AthleteRepository to an #Injectable instead of #Controller.
i have the problem that i have a circular dependency in my project. Unfortunately I cannot solve this with forwardRef.
The following structure:
OrderModule
OrderService
I have the following dependencies in the orderService
PriceService
CustomerService
SalePriceService
...
PriceModule
PriceService
I have the following dependencies in the priceService
OrderService
ProductService
...
I've tried all the options from the Official Documentation.
docs NestJs circular-dependency
What has to be considered here if there are more dependencies in a service?
Many thanks. Best regards.
Update:
order.module.ts
#Module({
imports: [
CustomerModule,
ProductModule,
MongooseModule.forFeature([{ name: 'Order', schema: OrderSchema }]),
forwardRef(() => PriceModule),
],
controllers: [OrderController],
providers: [OrderService],
exports: [OrderService],
})
export class OrderModule {}
order.service.ts
#Injectable()
export class OrderService extends GenericCrudService<OrderDocument> {
constructor(
#InjectModel(Order.name) readonly order: Model<OrderDocument>,
private readonly productService: ProductService,
#Inject(forwardRef(() => PriceService))
private readonly priceService: PriceService,
) {
super(order);
}
}
price.module.ts
#Module({
imports: [
CustomerModule,
SalePriceModule,
MongooseModule.forFeature([{ name: 'Price', schema: PriceSchema }]),
forwardRef(() => OrderModule),
],
controllers: [],
providers: [PriceService],
exports: [PriceService],
})
export class PriceModule {}
price.service.ts
#Injectable()
export class PriceService extends GenericCrudService<PriceDocument> {
constructor(
#InjectModel(Price.name) readonly price: Model<PriceDocument>,
private readonly customerService: CustomerService,
private readonly salePriceService: SalePriceService,
#Inject(forwardRef(() => OrderService))
private readonly orderService: OrderService,
) {
super(price);
}
}
product.module.ts
#Module({
imports: [
PriceModule,
MongooseModule.forFeature([{ name: 'Product', schema: ProductSchema }]),
],
controllers: [ProductController],
providers: [ProductService],
exports: [ProductService],
})
export class ProductModule {}
product.service.ts
#Injectable()
export class ProductService extends GenericCrudService<ProductDocument> {
constructor(
#InjectModel(Product.name) readonly product: Model<ProductDocument>,
) {
super(product);
}
}
The error I'm getting is:
The module at index [1] of the OrderModule "imports" array is undefined.
Potential causes:
- A circular dependency between modules. Use forwardRef() to avoid it. Read more: https://docs.nestjs.com/fundamentals/circular-dependency
- The module at index [1] is of type "undefined". Check your import statements and the type of the module.
Scope [AppModule -> ProductModule -> PriceModule]
Error: Nest cannot create the OrderModule instance.
The module at index [1] of the OrderModule "imports" array is undefined.
Potential causes:
- A circular dependency between modules. Use forwardRef() to avoid it. Read more: https://docs.nestjs.com/fundamentals/circular-dependency
- The module at index [1] is of type "undefined". Check your import statements and the type of the module.
Scope [AppModule -> ProductModule -> PriceModule]
So there's the obvious circular dependency that you have here: OrdersModule to PricesModule and back, that one is properly forwardReffed. However, there's another, not so obvious circular dependency too. OrdersModule to ProductsModule to PricesModule because the next import would be OrdersModule. Because of this, OrdersModule needs to forwardRef the ProductsModule and ProductsModule needs to forwardRef the PricesModule. It looks like the services themselves aren't circular, so it's just the modules that need the forward ref. Always make sure to check the entire import chain, especially when Nest is trying to report something like it did with Scope [AppModule -> ProductModule -> PriceModule].
I import a module in other module but a can access the service in other context
The module when i exported
#Module({
controllers: [ModuleController],
providers: [
ModulesAcessService,
ModulesRepository,
ModulesService
],
exports: [ModulesService, ModulesRepository, ModulesAcessService],
imports: [
TypeOrmModule.forFeature([ModuleEntity]),
forwardRef(() => CoursesModule),
forwardRef(() => LessonsModule)
]
})
export class ModulesModule { }
The module when i imported - ModulesModule
#Module({
controllers: [LessonsController],
providers: [
LessonsService,
LessonsAcessService,
LessonsRepository,
UserLessonsService,
UserLessonsRepository,
UserLessonsSubscriber,
UserLessonsEvents
],
exports: [LessonsRepository,LessonsService, LessonsAcessService, UserLessonsService],
imports: [
TypeOrmModule.forFeature([Lesson, UserLesson]),
forwardRef(() => CoursesModule),
forwardRef(() => ModulesModule)
]
})
export class LessonsModule { }
The error message
Nest can't resolve dependencies of the LessonsService (LessonsAcessService, UserLessonsService, UrlHelper, LessonsRepository, CoursesService, ?). Please make sure that the argument dependency at index [5] is available in the LessonsModule context.
The import in my service - I can't access the ModulesService.
import { ModulesService } from '../modules/modules.service';
#Injectable()
export class LessonsService {
constructor(
private lessonsAccessService: LessonsAcessService,
private userLessonsService: UserLessonsService,
private urlHelper: UrlHelper,
private lessonsRepository: LessonsRepository,
private coursesService: CoursesService,
private modulesService: ModulesService
) { }
...
Node version 14.7.0
Nestjs version 7
You need to make use of the forwardRef for the services too, not just the modules. In your ModulesService use #Inject(forwardRef(() => LessonsService)) on the lessonsService. In the LessonsService use #Inject(forwardRef(() => ModulesService)) on the modulesService.
I created service with several repository:
#Injectable()
export class DataService {
constructor(
#InjectRepository(ClassicPrices, 'connect')
private classicPrices: Repository<ClassicPrices>,
#InjectRepository(ModernPrices, 'connect')
private modernPrices: Repository<ModernPrices>,
) {}
public pricesRepository(server): Repository<ModernPrices | ClassicPrices> {
switch (server) {
case 'modern':
return this.modernPrices;
case 'classic':
return this.classicPrices;
}
}
}
Data module settings:
#Module({
imports: [
TypeOrmModule.forFeature([
ClassicPrices,
ModernPrices
], 'connect'),
],
providers: [DataService],
exports: [DataService]
})
export class DataModule {}
When I use it in another modules^ I have error "Nest can't resolve dependencies of the DataService (connect_ClassicPrices). Please make sure that the argument connect_ClassicPrices at index [2] is available in the DataModule context.
Potential solutions:
If connect_ClassicPrices is a provider, is it part of the current DataModule?
If connect_ClassicPrices is exported from a separate #Module, is that module imported within DataModule?
#Module({
imports: [ /* the Module containing connect_ClassicPrices */ ]
})
How to export repository ?
If you want to use a repository from DataModule in other modules you need to add TypeOrmModule to the exports array in DataModule:
exports: [DataService, TypeOrmModule]
Then, any module that imports DataModule can use the repositories registered with TypeOrmModule.forFeature. Generally it's a better practice to export just the services and keep the repositories scoped to their module because that makes your app more modular.
I get this error
Nest can't resolve dependencies of the WorkspaceController (?). Please make sure that the argument API_SERVICE at index [0] is available in the WorkspaceModule context.
I have this code
app.module.ts
#Module({
imports: [
ClientsModule.register([
{
name: 'API_SERVICE',
transport: Transport.REDIS,
options: {
url: 'redis://localhost:6379'
}
}
]),
WorkspaceModule
],
controllers: [AppController],
providers: [AppService]
})
workspace.module.ts
#Module({
imports: [],
controllers: [WorkspaceController]
})
export class WorkspaceModule {}
workspace.controller.ts
#Controller()
export class WorkspaceController{
constructor(#Inject('API_SERVICE') private client: ClientProxy) {}
#Get("default-languages")
getDefaultLanguages():Observable<string[]> {
return this.client.send<any>({cmd:'getDefaultLanguages'},{});
}
}
You register the ClientsModule inside of AppModule which means that controlelrs and providers in AppModule's scope (i.e. in its own providers and controllers arrays) have access to that provider (#Inject('API_SERVICE')), but once you leave to another module's scope (like WorkspaceModule), that provider is no longer available. If you need that microservice client in several different modules, I'd suggest making a wrapper module for it, that imports and exports the ClientsModule, otherwise, you just need to move the ClientsMOdule.register from AppModule to WorkspaceModule
Example Wrapper
#Module({
imports: [ClientsModule.register(clientsModuleOptions)],
exports: [ClientsModule],
})
export class WrapperClientsModule {}
It's called module re-exporting