NestJS can't resolve dependencies of the AuthServices - javascript

After first problem with JWT_MODULE_OPTION, back to old problem who I thought I was fixed. It turned out that when I "fix" old problem create the new with JWT.
So again can't compile:
Nest can't resolve dependencies of the AuthService (?, RoleRepository, JwtService). Please make sure that the argument at index [0] is available in the AppModule context. +25ms
It's really strange, because this way work on another my project and can't understand where I'm wrong. Here is the auth.service.ts:
#Injectable()
export class AuthService {
constructor(
#InjectRepository(User) private readonly userRepo: Repository<User>,
#InjectRepository(Role) private readonly rolesRepo: Repository<Role>,
private readonly jwtService: JwtService,
) { }
It get role and jwtService but the problem is with User, the path is correct. Here is app.module.ts:
#Module({
imports: [
TypeOrmModule.forRootAsync({
imports: [ConfigModule, AuthModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
type: configService.dbType as any,
host: configService.dbHost,
port: configService.dbPort,
username: configService.dbUsername,
password: configService.dbPassword,
database: configService.dbName,
entities: ['./src/data/entities/*.ts'],
}),
}),
],
controllers: [AppController, AuthController],
providers: [AuthService],
})
export class AppModule { }
Have the same compile error for controllers & providers & can't understand what is wrong...

You might be missing the TypeOrmModule.forFeature([User]) import. Typically, all entities are imported in dedicated feature modules. If you only have one module (i.e. AppModule) you need to put the forFeature import there in addition to the forRoot import.
#Module({
imports: [
TypeOrmModule.forRootAsync({...}),
TypeOrmModule.forFeature([User, Role]),
],

The global problem was that I try to add AuthService & AuthController twice. So I remove them from app.module.ts and just export AuthService from auth.module.ts:

Related

NestJS - JWTModule context dependency

After run my app i get this...
[Nest] 5608 - 01.01.2021, 18:12:05 [ExceptionHandler] Nest can't resolve dependencies of the JwtService (?). Please make sure that the argument JWT_MODULE_OPTIONS at index [0] is available in the JwtModule context.
Potential solutions:
- If JWT_MODULE_OPTIONS is a provider, is it part of the current JwtModule?
- If JWT_MODULE_OPTIONS is exported from a separate #Module, is that module imported within JwtModule?
#Module({
imports: [ /* the Module containing JWT_MODULE_OPTIONS */ ]
})
can someone tell me what i have wrong with my code?
#Module({
imports: [TypeOrmModule.forFeature([User]),
JwtModule.register({
secretOrPrivateKey: 'secret12356789'
})
],
providers: [UserService]
})
export class AuthModule { }
#Module({
imports: [
TypeOrmModule.forRoot({
//
}),
AuthModule,
UserModule,
JwtModule
],
controllers: [AppController, UserController, AuthController ],
providers: [AppService, UserService, AuthService ],
})
export class AppModule {}
thanks for any help
///////////////////////////////////////////////////////////////
In your AppModule you have the JwtModule imported but adding no options to it. This is what's causing the issue. As you already have the JwtModule registered in the AuthModule, this probably isn't what you're meaning to do.
You have the UserService registered in at least two places (AuthModule and AppModule), you're probably meaning to add the UserService to the exports of UserModule and then add the UserModule to the imports array of the module where you need the UserService.
TL;DR See, copy/paste examples.
Recently had the same issue.
As Nest.JS recommends the JwtModule could be declared in an authorization module: https://docs.nestjs.com/security/authentication. And, yes, it should be declared once with all its settings. The topic message could come from a multiple declaration (some of them has no JWT_MODULE_OPTIONS). Can wrap Jay's response with a prepared working example.
So the auth module should look like:
//./authorization/authorization.module.ts
import { Module } from '#nestjs/common';
import { JwtModule } from '#nestjs/jwt';
import { AuthorizationController } from './authorization.controller';
import { AuthorizationService } from './authorization.service';
#Module({
imports: [
...
JwtModule.register({
secret: process.env.ACCESS_TOKEN_SECRET || 'SOME_SECURE_SECRET_jU^7',
signOptions: {
expiresIn: process.env.TOKEN_EXPIRATION_TIME || '24h',
}
}),
....
],
controllers: [AuthorizationController],
providers: [AuthorizationService],
exports: [AuthorizationService, JwtModule]//<--here exports JwtModule
//as a part of AuthorizationModule
})
export class AuthorizationModule {};
Then your AppModule will inject the exported JwtModule from AuthorizationModule in this way.
//./app.module.js
import { Module } from '#nestjs/common';
import { AuthorizationModule } from './authorization/authorization.module';
#Module({
imports: [
...
AuthorizationModule, //<-- here injects the set up JwtModule
//NB! No additional injections required!
...
],
...
})
export class AppModule {};
Hope, this will help. ;)

Nest can't resolve dependencies of the UserService

I´m having this error
Nest can't resolve dependencies of the UserService (?, SettingsService). 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 */ ]
})
auth.module.ts
#Module({
imports: [
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({
secretOrPrivateKey: config.auth.secret,
signOptions: {
expiresIn: config.auth.expiresIn,
},
}),
UserModule,
SettingsModule,
],
controllers: [AuthController],
providers: [
AuthService,
JwtStrategy,
LocalStrategy,
UserService,
SettingsService,
Logger,
... other services,
],
exports: [PassportModule, AuthService],
})
export class AuthModule {}
user.module.ts
#Module({
imports: [
MongooseModule.forFeature([{ name: 'User', schema: UserSchema }]),
SettingsModule,
],
controllers: [UserController],
providers: [UserService],
exports: [UserService],
})
export class UserModule {}
app.module.ts
#Module({
imports: [
AuthModule,
UserModule,
SettingsModule,
MongooseModule.forRoot(config.db.url),
WinstonModule.forRoot({
level: config.logger.debug.level,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
user.service.ts
#Injectable()
export class UserService {
constructor(#InjectModel('User') private readonly userModel: Model<User>,
private readonly settingsService: SettingsService) {}
public async create(user: any): Promise<UserDto> {
...
}
I tried everything and can't find the issue, everything seems correct, i even checked every google page results to try to find it but i'm stuck.
The error tells me that i need to import UserModel into AuthModule, but it's already there, i tried to delete every single user model, or the AuthModule and mix them into everything and it still doesnt work, i know i have to export UserService to AuthModule, but can't find the correct way.
You are providing the UserService in your AuthModule. However, it should only be in your UserModule. In the AuthModule, the UserModel is unknown.
Double-check your module imports:
#Module({
imports: [
MongooseModule.forFeature([
{ name: 'User', schema: UserSchema }
]),
...
],
...
})
export class XModule {}
And look for silly mistakes! because even if you pass schema and schema name instead of each other, there will be no type errors! The general Nest can't resolve dependencies will be all you get for so many mistakes that are probable here...

Exporting variable in angular AoT compiler

I tried to implement dynamic configuration as can be seen in this post.
Everything works in JiT compiler, but I get
ERROR in Error during template compile of 'environment'
Function calls are not supported in decorators but 'Environment' was called.
when trying to build with the AoT compiler.
This is my environment.ts (note class Environment is exported):
export class Environment extends DynamicEnvironment {
public production: boolean;
constructor() {
super();
this.production = false;
}
}
export const environment = new Environment();
I would still like to use the environment in the standard way some.component.ts:
import { environment } from '../environments/environment';
console.log(environment.config.property);
Don't. Seriously, stay away from those two files (environment.ts and environment.prod.ts). Those are NOT about the DevOps meaning of the word "environment", they are about debug constants.
If you need to know if you're running a debug build, import isDevMode:
import { isDevMode } from '#angular/core';
If you need dynamic configuration, just read a Json from somewhere or have the server side inject it as a script tag, then read it directly or via Dependency Injection (it's not that hard to do).
But don't mess with those files. Trust me, you'll thank me later ;)
Solved this by creating config.module.ts and config.service.ts. Config module declares providers:
#NgModule({
providers: [
ConfigService,
{
provide: APP_INITIALIZER,
useFactory: (appConfigService: ConfigService) => () => appConfigService.loadAppConfig(),
deps: [ConfigService],
multi: true,
},
],
})
export class ConfigModule {}
Usage of config service in some.component.ts:
#Component(...)
export class SomeComponent {
constructor(private configService: ConfigService) { }
private myMethod() {
console.log(this.configService.get.property);
}
}
For tests, json testing config file is imported:
import { default as appTestConfig } from '../../../../assets/app-config.test.json';
and set directly on config service:
TestBed.configureTestingModule({
...,
imports: [
ConfigModule,
...
],
providers: [
{
provide: APP_INITIALIZER,
useFactory: (appConfigService: ConfigService) => () => appConfigService.setConfig(appTestConfig),
deps: [ConfigService],
multi: true,
},
]
}).compileComponents();

Routing Module loads before APP_INITIALIZER

I have a value that is from of a config file from static AppConfigService.
Described below:
reference code/article: https://blogs.msdn.microsoft.com/premier_developer/2018/03/01/angular-how-to-editable-config-files/
import { Injectable } from '#angular/core';
import { AppConfig } from './app-config';
import { HttpClient } from '#angular/common/http';
import { environment } from 'src/environments/environment';
#Injectable()
export class AppConfigService {
static settings: AppConfig;
constructor(private http: HttpClient) { }
load() {
console.log('is this getting fired before routing module check?');
const jsonFile = `assets/config/config.${environment.name}.json`;
return new Promise<void>((resolve, reject) => {
this.http.get(jsonFile)
.toPromise()
.then((response: AppConfig) => {
AppConfigService.settings = <AppConfig>response;
console.log(AppConfigService.settings);
resolve();
})
.catch((response: any) => {
reject(`Could not load file '${jsonFile}':
${JSON.stringify(response)}`);
});
});
}
}
This config gets loaded in my APP_INITIALIZER in the app.module.ts
providers: [
AppConfigService,
{
provide: APP_INITIALIZER,
useFactory: (appConfigService: AppConfigService) => () => {appConfigService.load() },
deps: [AppConfigService], multi: true
}
],
but my routing module, named AppRoutingModule is reading something out of my AppConfigService.settings variable which is crazy enough, UNDEFINED. My application crashes. I expect the APP_INITIALIZER to fire BEFORE AppRoutingModule but this is not the case:
Uncaught TypeError: Cannot read property 'oldUrl' of undefined
oldUrl is a property of AppConfigService.settings. I checked if AppConfigService.settings is set, it IS, properly AFTER routing module is fired but this is not what I want.
I checked some other sources for help. I used the following already as maybe a fix: https://github.com/angular/angular/issues/14615 and https://github.com/angular/angular/issues/14588
#component({})
class App {
constructor(router: Router, loginService: LoginService) {
loginService.initialize();
router.initialNavigation();
}
}
#NgModule({
imports: [
BrowserModule,
RouterModule.forRoot(routes, {initialNavigation: false})
],
declarations: [ App ],
bootstrap: [ App ],
providers: [ Guard, LoginService ]
})
export class AppModule {
}
Unfortunately, the above solution is not fixing my problem. I also tried to put in AppModule but alas, that didn't help either.
Any help is very welcome.
I've solved my App Initialization and Routing with NgRx listening the central state to know when the system is Loaded and activating the route Guards after that.
But for a direct solution, you need to add a Route Guard checking when your service is loaded. So, add a loaded: boolean flag in your Service, and check it from a Guard like this:
https://github.com/angular/angular/issues/14615#issuecomment-352993695
This is better handled with Observables tho, and I'm wiring all with NgRx in my Apps using Facades to facilitate everything:
https://gist.github.com/ThomasBurleson/38d067abad03b56f1c9caf28ff0f4ebd
Best regards.

Invalid provider error when injecting service into service in Angular 2

I currently have a module setup like below (exerpt);
AppModule
RoutingModule
AuthRouteGuard
AuthModule
LoginFormComponent
AuthService
I have defined my AuthService (responsible for handling user authentication and provides a method for determining whether the current user is authenticated) as a provider in my AuthModule;
// auth.module.ts - uses https://github.com/auth0/angular2-jwt
export function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig({
tokenName: jwtLocalStorageKey
}), http, options);
}
export let authHttpServiceProvider = {
provide: AuthHttp,
useFactory: authHttpServiceFactory,
deps: [Http, RequestOptions]
};
#NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule
],
exports: [AuthComponent],
declarations: [AuthComponent, LoginComponent, RegisterComponent],
providers: [
AuthService,
authHttpServiceProvider
]
})
export class AuthModule { }
I can use this service with no problem within its sibling LoginFormComponent. When I attempt to use the AuthService within the AuthRouteGuard class in the RoutingModule however I get the following error;
Error: Invalid provider for the NgModule 'AuthModule' - only instances of Provider and Type are allowed, got: [?undefined?, ...]
I have the AuthModule imported within the RoutingModule. The error above occurs as soon as the AuthService is defined as a dependency for the AuthRouteGuard;
export class AuthRouteGuard implements CanActivate {
constructor(
private router: Router,
private authService: AuthService // Removing this injection removes the error
) {}
canActivate() {
// #todo: if not authenticated
this.router.navigate(['/login']);
return true;
}
}
What am I missing here, and why would injecting the service in the constructor cause an invalid provider error that does not occur when that injection is removed?
Edit - Same error occurs if the authHttpServiceProvider provider is removed altogether, so the AuthModule module looks like;
#NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule
],
exports: [AuthComponent],
declarations: [AuthComponent, LoginComponent, RegisterComponent],
providers: [
AuthService
]
})
export class AuthModule { }
Add authHttpServiceProvider to imports of the module. It's exported to global and not available to module. So you can't provide the service because you have unknown provider to the module.
#NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule
],
exports: [AuthComponent],
declarations: [AuthComponent, LoginComponent, RegisterComponent],
providers: [
AuthService
]
})
export class AuthModule {
The actual problem was within the AuthService itself.
AuthModule defined a constant;
export const jwtKey = 'jwt';
Which was being imported into the AuthService and used;
import { jwtKey } from '../auth.module';
For some reason if I remove this import everything works fine.

Categories