I am fairly new to nestJs. I am trying to implement an authentication process according to nestjs documentation, but I don't want to route the login in the app.controller I want to put it in the users.controller, so the route will be /users/login. However, since the AuthModule already uses the UsersService in my code and the login logic with JWT is in the AuthService. Importing it back to the UsersService create a circular dependency. I need help.
To avoid circular dependancy, in your UsersModule, you need to import your AuthModule with ForwardRef like that :
import ...
#Module( {
imports: [
forwardRef( () => AuthModule ),
],
controllers: [],
providers: [],
exports: []
} )
export class UsersModule {
}
If you haven't already done so, you'll need to export the AuthService in AuthModule :
import ...
#Module( {
imports: [],
controllers: [],
providers: [],
exports: [
AuthService
]
} )
export class AuthModule {
}
Related
In a NestJs project, I created a module that uses, DiscoveryService in the services. It working fine. I wanted to create a nest library from that module. I followed this nestJs documentation then I am getting the below error. I tried both adding ModulesContainer in to my module imports and providers. nothing helped.
[Nest] 65775 - 10/12/2022, 11:55:03 AM ERROR [ExceptionHandler] Nest can't resolve dependencies of the DiscoveryService (?). Please make sure that the argument ModulesContainer at index [0] is available in the DiscoveryModule context.
Error log
Potential solutions:
If ModulesContainer is a provider, is it part of the current DiscoveryModule?
If ModulesContainer is exported from a separate #Module, is that module imported within DiscoveryModule? #Module({
imports: [ /* the Module containing ModulesContainer */ ] })
Error: Nest can't resolve dependencies of the DiscoveryService (?).
Please make sure that the argument ModulesContainer at index [0] is
available in the DiscoveryModule context.
library
import { DiscoveryService } from '#nestjs/core';
#Injectable()
export class EventPublishingService {
private readonly logger = new Logger(EventPublishingService.name);
private readonly publishingEventProviders;
constructor(
private discoveryService: DiscoveryService
) {
this.publishingEventProviders = this.discoveryService
.getProviders()
.filter(
({ metatype }) =>
metatype && Reflect.getMetadata(PUBLISHABLE_METADATA, metatype),
);
}
}
#Global()
#Module({
imports: [DiscoveryModule, HttpModule, ConfigModule],
providers: [
EventRegistrationService,
EventManagerServiceApi,
EventPublishingService],
exports: [EventPublishingService],
})
export class EventManagerModule {}
app module
#Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
cache: true,
load: [configuration],
}),
ScheduleModule.forRoot(),
MongooseModule.forRootAsync({
imports: [DataVaultManagerModule],
inject: [DataVaultManager],
useClass: MongooseConfigService,
}),
ParticipantsModule,
StudiesModule,
HealthModule,
EventManagerModule,
UsersModule,
],
controllers: [AppController],
providers: [
AppService,
{
provide: APP_PIPE,
useClass: ZodValidationPipe,
},
],
})
export class AppModule {}
Try changing constructor from EventPublishingService class like below:
constructor(
#Inject(DiscoveryService) private discoveryService: DiscoveryService
)
So, I have my RootModule, a ProductModule and a StoreModule.
My RootModule:
#Module({
imports: [
ProductModule,
StoreModule,
],
controllers: [],
providers: [],
})
export class RootModule {}
My ProductModule:
#Module({
providers: [ProductService],
exports: [],
})
export class ProductModule {}
My StoreModule:
#Module({
imports: []
providers: [StoreService, StoreWaitingService],
})
export class ProductModule {}
Since my RootModule imports ProductModule, shouldn't I be able to use ProductService on StoreService and StoreWaitingService?
What if I imported ProductModule on StoreModule imports?
You can use Product Module and Service in StoreService
Product Module
#Module({
providers: [ProductService],
exports: [ProductService],
})
export class ProductModule {}
Store Module
#Module({
imports: [ProductModule],
})
export class StoreModule{}
Store service
import ProductService from '<Product Service Path>';
...
constructor(private readonly productService: ProductService){}
...
//in Function
this.productService.someFunction();
But if you don't want to import the product module in Store Module, you can make the Product Module a global Module -
https://docs.nestjs.com/modules#global-modules
I am using #nestjs/jwt in my NestJS project.
I have two modules, AuthModule and AppModule.
The AuthModule uses the #nestjs/jwt
The AppModule invoke auth service from AuthModule.
AuthService:
import { Injectable } from '#nestjs/common';
import { JwtService } from '#nestjs/jwt';
import { ForbiddenException } from '#nestjs/common';
#Injectable()
export class AuthService {
constructor(private readonly jwt: JwtService) {}
async validate(token: string) {
return this.jwt.verify(token);
}
...
}
AuthModule:
import { Module } from '#nestjs/common'
import { TokenService } from './auth.service'
import { ConfigModule, ConfigService } from '#nestjs/config'
import { JwtModule } from '#nestjs/jwt'
#Module({
imports: [
JwtModule.register({
secret: "mysecret",
signOptions: { expiresIn: "60s" },
}),
],
// I provide AuthService & JwtService
providers: [AuthService, JwtService],
// I export AuthService and JwtService
exports: [AuthService, JwtService],
})
export class AuthModule {}
AppModule:
#Module({
imports: [
AuthModule,
...
],
controllers: [AppController],
// I provide AuthService & JwtService also in AppModule
providers: [AppService, JwtService],
})
export class AppModule {}
(The AppController invokes AuthService instance to validate token.)
I constantly get error:
Nest can't resolve dependencies of the JwtService (?). Please make sure that the argument JWT_MODULE_OPTIONS at index [0]
Why is that? Where do I miss?
You don't need to add JwtService to the providers. Nest will look through the current module's providers, then the imported module's exports, and then the global module's exports to find providers that are not immediately in the level it's resolving the providers in. This means that for AuthService it'll look up to the JwtModule's exports and find the JwtService already created, and use that instance. Then in the AppModule you don't need to mention the AuthService or JwtService, just import the AuthModule that exports the AuthService and JwtModule (doing some module re-exporting) and you should be good to go
EDIT: Added module code:
AuthModule
import { Module } from '#nestjs/common'
import { TokenService } from './auth.service'
import { ConfigModule, ConfigService } from '#nestjs/config'
import { JwtModule } from '#nestjs/jwt'
#Module({
imports: [
JwtModule.register({
secret: "mysecret",
signOptions: { expiresIn: "60s" },
}),
],
providers: [AuthService],
exports: [AuthService, JwtModule],
})
export class AuthModule {}
AppModule
#Module({
imports: [
AuthModule,
...
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
I have own implementation of AuthGuard:
import { authenticate } from 'passport';
#Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext){
...
authenticate(...);
}
}
When I call authenticate method I get: Cannot read property 'authenticate' of undefined at Authenticator.authenticate (.../node_modules/passport/lib/authenticator.js:162:26
It looks like Passport hasn't been started.
AuthModule:
#Module({
imports: [PassportModule],
providers: [
AuthGuard,
{
provide: APP_GUARD,
useClass: AuthGuard,
},
],
})
export class AuthModule {}
and AppModule:
#Module({
imports: [
AuthModule
]
})
export class AppModule {}
This code was working in Nest 7.
Do you have any idea what could be wrong?
I am trying to inject a ContentsService into a SlackModule so that I can use some of the Content functions in my Slack Controller.
This is app.module
#Module({
imports: [
ContentsModule,
ZapierModule,
SlackModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Here is my Contents Module:
import { Module } from '#nestjs/common';
import { MongooseModule } from '#nestjs/mongoose';
import { ContentsController, ZapierController, SlackInteractiveController } from './contents.controller';
import { ContentsService } from './contents.service';
import { ContentSchema } from './content.model';
#Module({
imports: [
MongooseModule.forFeature([{ name: 'Content', schema: ContentSchema }]),
],
controllers: [ContentsController, ZapierController, SlackInteractiveController],
providers: [ContentsService],
exports: [ContentsService],
})
export class ContentsModule {}
This is my Slack Module:
import { Module } from '#nestjs/common';
import { SlackService } from './slack.service';
import { SlackController } from './slack.controller';
import { ContentsService } from '../contents/contents.service';
#Module({
providers: [SlackService],
controllers: [SlackController],
imports: [ContentsService],
})
export class SlackModule {}
And my Slack Controller
import { ContentsService } from '../contents/contents.service'
#Controller('slackevents')
export class SlackController {
constructor(private contentsService: ContentsService) {}
But when I run this code, I get this error:
[Nest] 75628 - 05/22/2020, 7:08 AM [ExceptionHandler] Nest can't resolve dependencies of the ContentsService (?). Please make sure that the argument at index [0] is available in the ContentsService context. +44ms\
What is it that I am doing wrong?
Services and other providers do not belong in the imports array. Only module classes should go in there. You should have imports: [ContentsModule] in your SlackModule and you'll have access to the ContentsService