Nest can't resolve dependencies of AuthService - nestjs

I am following the documentation present here
https://docs.nestjs.com/techniques/authentication#jwt-functionality
To have faster support I have created a git repository with the problem
https://github.com/Sano123456/nestjs-jwt
node -v -> v10.15.2
npm -v -> 6.14.6
nest -v -> 7.4.1
First Problem:
in AuthModule if I do as described in documentation and just import UserModule, it return me error of circular dependency between UserModule and AuthModule
#Module({
imports:[
UsersModule,
PassportModule
],
providers: [AuthService],
controllers: [AuthController],
exports:[AuthService, LocalStrategy]
})
export class AuthModule {}
error:
[ExceptionHandler] Nest cannot create the AuthModule instance.
The module at index [0] of the AuthModule "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 [0] is of type "undefined". Check your import statements and the type of the module.
Scope [AppModule -> UsersModule] +6ms
Possibile solution in imports array of AuthModule instead of UserModule put forwardRef(() => UsersModule),
this actually remove the error but not sure if this is the right way
Second problem:
it says that can't find LocalStrategy class even if it's present and declared in AuthModule
[ExceptionHandler] Nest cannot export a provider/module that is not a part of the currently processed module (AuthModule). Please verify whether the exported LocalStrategy is available in this particular context.Is LocalStrategy part of the relevant providers/imports within AuthModule?
Possibile solution right now I don't have any solution, I just remove it to understand what is the problem
Third problem :
after removing LocalStrategy,
[ExceptionHandler] Nest can't resolve dependencies of the AuthService (?). Please make sure that the argument dependency at index [0] is available in the AuthModule context.
Potential solutions:
- If dependency is a provider, is it part of the current AuthModule?
- If dependency is exported from a separate #Module, is that module imported within AuthModule?
#Module({
imports: [ /* the Module containing dependency */ ]
})
+1ms
Error: Nest can't resolve dependencies of the AuthService (?). Please make sure that the argument dependency at index [0] is available in the AuthModule context.
anyone solved this issues?

You have a circular dependancy because your UsersModule and your AuthModule import each other. Therefore you have 2 options to repair this issue.
The first is to make a forward reference which will allow both modules to be built simultaneously and once built, pass in the reference required. This is done like so:
#Module({
imports: [
forwardRef(() => UsersModule),
],
...
})
export class AuthModule {}
// And the same for your UsersModule
#Module({
imports: [
forwardRef(() => AuthModule),
],
})
export class UsersModule {}
The second option is to remove the dependancies from one another. This is not always possible and guessing by the names of your modules I would argue this isn't possible. You don't want to have the auth module accessing the user module's database and services etc outside the users module. But I'll give you some advice on module inheritance.
Module in nestjs are built asynchronously. Meaning they have to be structured like a cascading tree with one module importing all the others. Something linear will look like this
AppModule <= CatModule <= PawsModule
Another example would be dual importing
<= CatModule
AppModule <= PawsModule
<= DogModule
In the above example, the paws module is created once and imported in both cat and dog module. Meaning paws module will be built first before cat and dog module.
So to explain your error you need to think from a linear code perspective and how the module import tree will share modules that import each other. Because they import each other, nest can't decide which to create first so will need a reference to pass back, hence the function. I've always imagined the container's forward ref function as saying "Hey, hold this for a sec" (it's a piece of paper that says "UsersModule") then turns around, does some wavey of the arms with his back turned, then turns around and replaces the piece of paper with the UsersModule!
Your second issue is you never created a provider for LocalStrategy. It doesn't exist in the AuthModule so cannot be imported into AuthService nor exported from AuthModule!

** SOLUTION of problem "can't resolve dependencies" **
For the first and second problem the final solution is to use #Inject(forwardRef(() => AuthService)) in UserService
here is example
#Injectable()
export class UserService {
constructor(
#InjectRepository(User) private readonly UserRepository: Repository<User>,
private readonly config: ConfigService,
#Inject(forwardRef(() => AuthService)) //<---
private readonly authService: AuthService,
) {
}
Same thing also in AuthService
#Injectable()
export class AuthService {
private client: any;
constructor(
#Inject(forwardRef(() => UserService))//<--- here
private readonly userService: UserService,
#InjectConfig() private readonly config,
) {
}
In AuthModule and UserModule you need to still use forwardRef
I never used this solution before and i never needed it, but this solved my issue
Regarding LocalStrategy, put it in providers array of the module

For me, it wasn't enough to just use the forwardRef on both services as in Sano's answer; I also had to forwardRef on both circular dependent modules too.
In both services:
https://docs.nestjs.com/fundamentals/circular-dependency#forward-reference
import { forwardRef, Inject } from '#nestjs/common';
...
#Inject(forwardRef(() => UserService))`
In both modules:
https://docs.nestjs.com/fundamentals/circular-dependency#module-forward-reference
import { forwardRef } from '#nestjs/common';
...
imports: [
forwardRef(() => UsersModule),
],

Related

Nest.js cant't resolve circular dependencencies

I am currently running into this nasty problem, and after hours of searching, I have only found a semi-satisfying solution so far. I am curious if anybody has experienced something similar:
I get the usual error message:
ERROR [ExceptionHandler] Nest can't resolve dependencies of the InventoryElementsService (PrismaService, ?, AuthorizerService). Please make sure that the argument dependency at index [1] is available in the InventoryElementsModule context.
Looking at the constructor of InventoryElements.service.ts, I see that the NotificationsSerivce is not properly injected:
#Injectable()
export class InventoryElementsService {
constructor(
private readonly prisma: PrismaService,
private readonly notificationsService: NotificationsService,
private readonly authorizer: AuthorizerService,
) { }
...
}
Looking at the corresponding InventoryElements.module.ts it seems like I do import it properly:
#Module({
imports: [
forwardRef(() => UsersModule),
forwardRef(() => UserPreferenceModule),
forwardRef(() => NotificationsModule),
forwardRef(() => InventoryAttributesModule),
AuthorizerModule
],
providers: [
InventoryElementsResolver,
InventoryElementsService,
PrismaService,
],
exports: [InventoryElementsService]
})
export class InventoryElementsModule {}
It is a circular dependency and therefore I use forwardRef(() => ...).
The imported notifications.module.ts also seems to be initialised correctly and the notifications.service.ts is also marked with Injectable():
#Module({
imports: [
forwardRef(() => UserPreferenceModule),
forwardRef(() => InventoryElementsModule),
EmailModule
],
providers: [
NotificationsResolver,
NotificationsService,
PrismaService
],
exports: [NotificationsService]
})
export class NotificationsModule {}
Now, interestingly, if I inject NotificationsService inline into the InventoryElements.service.ts-constructor directly, it works:
#Injectable()
export class InventoryElementsService {
constructor(
private readonly prisma: PrismaService,
#Inject(forwardRef(() => NotificationsService)) private readonly notificationsService: NotificationsService,
private readonly authorizer: AuthorizerService,
) { }
This solution does not seem ideal, and I am pretty sure that there is something wrong with my code, but I am really running out of options, where to look for mistakes (and yes, I have already double-checked my imports, and all modules are also imported in app.module.ts 🙈)
Thanks for any help, and stay healthy!
You already mentioned what the fix is: add #Inject(forwardRef(() => OtherService)) to both of the service's constructors. forwardRef is necessary in both the module and the provider because both the modules are circular with each other and both of the services are circular with each other. The point of the forwardRef method is to have a lazy evaluator so that Node can end up creating the class references and have function references to the circular classes, without getting into a unresolvable loop of A needs B needs A

NestJS. Can't inject a repository from a different module

I am trying to use a typeorm custom repository defined in another module.
Following the documentation:
If you want to use the repository outside of the module which imports TypeOrmModule.forFeature, you'll need to re-export the providers generated by it. You can do this by exporting the whole module, like this:
#Module({
imports: [TypeOrmModule.forFeature([Role])],
exports: [TypeOrmModule]
})
export class RoleModule {}
Now if we import UsersModule in UserHttpModule, we can use #InjectRepository(User) in the providers of the latter module.
In my case i do:
#Module({
imports: [RoleModule],
providers: [UsersService],
controllers: [UsersController]
})
export class UserModule {}
Now when i inject the Role repository
export class UserService {
constructor(#InjectRepository(Role) private roleRepository: Repository<Role>) {}
}
i've got an error:
Nest can't resolve dependencies of the UserService (?).
Is it me or is the documentation incorrect?
Can someone suggest what is the error here or give a corrected example?
Try to add TypeOrmModule.forFeature([Role]) to imports:
#Module({
imports: [TypeOrmModule.forFeature([Role]), RoleModule], // <-- here
providers: [UsersService],
controllers: [UsersController]
})
export class UserModule {}

Nestjs cannot resolve dependency index[0] when decorator is being used

I am new to NestJs and i have a question for you that i could not resolve it.
UsersService has two dependencies
-TypeOrm UsersRepository Injection
-WalletsService Injection
Typeorm injection is done by decorator as you see down below.
//UsersService
#Injectable()
export class UsersService implements IUserService {
constructor(
#InjectRepository(Users)
private usersRepository: Repository<Users>,
private readonly walletsService: WalletsService,
) { }
Whenever i changed first injection it cannot be resolved.
Probably i am missing something. There are all photos down below with description
//UsersModule
#Module({
controllers: [UsersController],
exports: [UsersService],
imports: [WalletsModule, TypeOrmModule.forFeature([Users])],
providers: [UsersService],
})
export class UsersModule { }
//WalletsModule
#Module({
controllers: [WalletsController],
exports: [WalletsService],
imports: [TypeOrmModule.forFeature([Wallets])],
providers: [WalletsService]
})
export class WalletsModule { }
[When Users Repository is first injection]
Nest can't resolve dependencies of the UsersService (?, WalletsService). Please make sure that the argument UsersRepository at index [0] is available in the UsersService context.
Potential solutions:
- If UsersRepository is a provider, is it part of the current UsersService?
- If UsersRepository is exported from a separate #Module, is that module imported within UsersService?
#Module({
imports: [ /* the Module containing UsersRepository */ ]
})
[When Wallets Service is first injection ]
Nest can't resolve dependencies of the UsersService (?, UsersRepository). Please make sure that the argument WalletsService at index [0] is available in the UsersService context.
Potential solutions:
- If WalletsService is a provider, is it part of the current UsersService?
- If WalletsService is exported from a separate #Module, is that module imported within UsersService?
#Module({
imports: [ /* the Module containing WalletsService */ ]
})
Thank you in advance. I hope it is descriptive enough. Have good day!
For posterity of the answer from the comments:
There was a service in an imports array which leads to problems with Nest trying to resolve things. In general, these errors can start to be debugged knowing that Nest's error is in the form of
Nest can't resolve dependencies of the UsersService (<dependencies_with_unknown_as_?>. Please make sure that the argument <unknown_dependency> at index [] is available in the <related_module> context.

Using imported interceptor on controller not working in nestjs

I like to organise my project along feature lines with different modules for cross cutting concerns eg: configuration, authentication, etc. However when importing an Interceptor into a feature module for use with a Controller Nest doesn't seem to reuse the existing instance.
controllers.module.ts
#Module({
imports: [
// ConfigService is exported from this module.
ConfigModule
],
providers: [
// For debugging purposes I used a factory so I could place a breakpoint and see
// when the Interceptor is being created.
{
provide: MyInterceptor,
useFactory: (config: ConfigService) => new MyInterceptor(config),
inject: [
ConfigService
]
}
],
exports: [
MyInterceptor
]
})
export class ControllersModule {
}
customer.module.ts
#Module({
imports: [
ControllersModule
],
controllers: [
CustomerController
],
providers: [
CustomerService
]
})
export class CustomerModule {
}
customer.controller.ts
#Controller("/customers")
#UseInterceptors(MyInterceptor)
export class CustomerController {
constructor(private readonly customerService: CustomerService) {
}
#Get()
customers() {
return this.customerService.findAll();
}
}
When the application starts up, I can see the MyInterceptor provider factory being called, with an instance of ConfigService. However then I see the following error on the console
error: [ExceptionHandler] Nest can't resolve dependencies of the MyInterceptor (?). Please make sure that the argument ConfigService at index [0] is available in the CustomerModule context.
Potential solutions:
- If ConfigService is a provider, is it part of the current CustomerModule?
- If ConfigService is exported from a separate #Module, is that module imported within CustomerModule?
#Module({
imports: [ /* the Module containing ConfigService */ ]
})
Now maybe there's something about how Nest instantiates/uses Interceptors that I'm not understanding but I thought that given that MyInteceptor had been created, and the ControllersModule imported by CustomerModule that the bean would have been available and applied to CustomerController.
Is there something I'm missing here?
Interceptors (along with other request lifecycle classes) are kinda like pseudoproviders in that that are #Injectable() but they aren't added to a providers array for binding. You can bind then via the providers array, (APP_INTERCEPTOR) but that will cause it to be bound globally.
Because interceptors can't be added to a providers array the way you are trying, you need to instead add the ConfigModule to whatever module uses the interceptor.
and as a side-note, you shouldn't use #Res with interceptors in nestjs
why
look, when you are using an interceptor, you are handling (with using .handle()) the stream of response (observable) not a whole package of it, but using express #Res actually is somehow getting around the whole flow of response streaming.
this is also explicitly mentioned in nestjs official documents:
We already know that handle() returns an Observable. The stream
contains the value returned from the route handler, and thus we can
easily mutate it using RxJS's map() operator.
WARNING
The response mapping feature doesn't work with the
library-specific response strategy (using the #Res() object directly
is forbidden).

NestJS cannot verify argument is available in current context/Mongoose Inject Model

I followed the MongoDB tutorial on the nestjs website but am unable to replicate it in my own project, I have cloned the nextjs repo and verified that the mongo sample supplied there runs fine.
This is what I currently have (minified):
app.module.ts
#Module({
imports: [
MongooseModule.forRoot('mongodb://localhost/nest')
],
modules: [
CampaignModule
]
})
export class AppModule implements NestModule {}
}
campaign.module.ts
#Module(
{
modules: [SharedModule],
controllers: [CampaignController],
components: [CampaignService],
imports: [MongooseModule.forFeature([{name: 'Campaign', schema: campaignSchema}])]
})
export class CampaignModule {}
campaign.service.ts
#Component()
export class CampaignService {
constructor(#InjectModel(campaignSchema) private readonly campaignModel: Model<CampaignInterface>) {}
}
this builds fine as expected but when I run it i get this error:
Nest can't resolve dependencies of the CampaignService (?). Please verify whether [0] argument is available in the current context.
So because in my app.module.ts I have the campaign module in the modules section (how i have had it so far working fine prior to mongodb) I moved it into the imports sections with the MongooseModule now it will build and run fine, but the routes inside the controller for campaign.controller.ts do not register at all, they just return 404's. This is weird because the example in the nestjs repo have the CatsModule inside the imports with the MongooseModule and it works.
Any tips here would be appreciated. this is my schema and interface for the campaign object as well:
export interface CampaignInterface extends Document, Campaign {
}
export const campaignSchema: any = new mongoose.Schema({
campaignId: String
});
EDIT 1
I moved all my modules into the import section of my app.module.ts file as before I tried it with CampaignModule in imports and all the others in modules: []. It now fails right away when served with the same error and no routes are registered.
Ok I figured out what is going on,
It seems that if you have both a modules: [] and imports: [] inside your #Module decorator the modules: [] takes over and completely ignores the imports: []. So in my campaign.module.ts file I moved the SharedModule from modules: [] into imports: [] after the MongooseModules.forFeature import. It now works and write to mongo!

Resources