Reputation: 394
I'm trying to create my custom JwtModule
. I made JwtModule
a dynamic module so that I can provide a private key using dotenv
.
jwt.module.ts :
import { DynamicModule, Module } from '@nestjs/common';
import { CONFIG_OPTIONS } from './jwt.constants';
import { JwtModuleOptions } from './jwt.interfaces';
import { JwtService } from './jwt.service';
@Module({})
export class JwtModule {
static forRoot(options: JwtModuleOptions): DynamicModule {
return {
module: JwtModule,
providers: [
{
provide: CONFIG_OPTIONS,
useValue: options,
},
JwtService,
],
exports: [JwtService],
};
}
}
jwt.service.ts :
import { Inject, Injectable } from '@nestjs/common';
import { CONFIG_OPTIONS } from './jwt.constants';
import { JwtModuleOptions } from './jwt.interfaces';
@Injectable()
export class JwtService {
constructor(
@Inject(CONFIG_OPTIONS) private readonly options: JwtModuleOptions,
) {}
// I will do something here
}
users.module.ts :
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { JwtModule } from 'src/jwt/jwt.module';
import { User } from './entities/user.entity';
import { UsersResolver } from './users.resolver';
import { UsersService } from './users.service';
@Module({
imports: [TypeOrmModule.forFeature([User]), JwtModule],
providers: [UsersResolver, UsersService],
})
export class UsersModule {}
users.service.ts :
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { InternalServerErrorOutput } from 'src/common/common.constants';
import { JwtService } from 'src/jwt/jwt.service';
import { Repository } from 'typeorm';
import {
CreateAccountInput,
CreateAccountOutput,
} from './dtos/create-account.dto';
import { User } from './entities/user.entity';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>,
private readonly jwtService: JwtService,
) {}
// I will do something here
}
I imported JwtModule into app.module.ts
like this :
JwtModule.forRoot({ privateKey: process.env.JWT_PRIVATE_KEY })
However, when I try to run this application, the console prints an error:
Nest can't resolve dependencies of the UsersService (UserRepository, ?).
Please make sure that the argument JwtService at index [1] is available in the UsersModule context.
Potential solutions:
- If JwtService is a provider, is it part of the current UsersModule?
- If JwtService is exported from a separate @Module, is that module imported within UsersModule?
@Module({
imports: [ /* the Module containing JwtService */ ]
})
Since I exported JwtService
and imported JwtModule
into UsersModule
, so what the error suggests does not help. Using @Global
to JwtModule
is a simple solution, but as I will not use JwtModule elsewhere, so I would like to know the way without making it global. Any help would be greatly appreciated. Thank you!
Upvotes: 2
Views: 1685
Reputation: 70131
Dynamic modules are just that, dynamic. They need to have their configuration/registration methods called when they are about to be made of use. You register the JwtModule
in your AppModule
, but not in your UserModule
, so UserModule
doesn't see the returned module with the JwtService
exported, it sees a module with no providers and no exports. There's a couple of ways around this,
you can register the JwtModule
in the UserModule
directly, if you aren't going to re-use this, it might not be a bad idea
you can create a wrapper module tat imports the JwtModule.forRoot()
and exports the JwtModule
, then you import the wrapper module where you need the JwtModule
and get back the configured module each time
this is mostly overkill, but cool to know, you can follow the RxJS Subject approach in this repository that would allow you to do something like JwtMoule.externallyConfigured(0)
and get the configuration that was made in AppModule
. Again, overkill, but cool
Upvotes: 2