At Tevpro we really like NestJS, it is a great framework for building server side typescript. It takes much of its inspiration from Angular. One of the most loved (and occasionally hated) features of Angular is its Dependency Injection (DI) framework. The NestJS team has done a nice job of bringing this DI framework to the server side. Being server side there are some notable differences, but all things considered, it's a refreshing change.

I ran into a familiar issue while building a new module, but was a bit baffled by the solution. First, frequently, I like to use index.ts files to simplify imports when multiple classes from the same folder need to be imported. Simple.

// index.ts

export * from './auth.controller';
export * from './auth.service';
export * from './constants';
export * from './jwt.strategy'
export * from './jwt-auth.guard';
export * from './local.strategy';
export * from './local-auth.guard';

Anyway, I had completed authoring my module and was about to start testing/debugging when I encountered a familiar error. The DI framework was unable to resolve on the dependencies (AuthService) in the AuthContoller.

// auth.contoller.ts

import { Controller, UseGuards, Req, Body } from '@nestjs/common';
import { AuthService, LocalAuthGuard, JwtAuthGuard } from '.';
import { Request } from 'express';
import { AuthGuard } from '@nestjs/passport';

@Controller('auth')
export class AuthController {

    constructor(
    private readonly authService: AuthService
    ) {}
    ...
}

Error

Nest can't resolve dependencies of the AuthController (?). 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 */ ]
  })

Normally this would be resolved by simply importing the module that contained AuthService or adding AuthService as a provider. However, in this particular case AuthService was part of the AuthModule and had already been added to the providers.

// auth.module.ts

import { Module } from '@nestjs/common';
import { UserModule } from '../user/user.module';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';
import { jwtConstants, LocalStrategy, JwtStrategy, AuthController, AuthService } from '.';
import { LoggerModule } from '~/shared/services/log';

@Module({
    imports: [
        LoggerModule.forRoot(),
        UserModule,
        PassportModule.register({ defaultStrategy: 'local' }),
        JwtModule.register({
            secret: jwtConstants.secret,
            signOptions: { expiresIn: '60s' },
        }),
    ],
    providers: [
        AuthService,
        LocalStrategy,
        JwtStrategy,
    ],
    exports: [
        AuthService,
        PassportModule,
    ],
    controllers: [AuthController],
})
export class AuthModule {}

The solution ended up being something I've encountered before but had long forgotten. Sometimes in DI, order seems to matter. Its not always in the place you might expect. Ultimately the solution was to re-order the index.ts file to move the controller to the bottom of the list.

// index.ts

export * from './auth.service';
export * from './constants';
export * from './jwt.strategy'
export * from './jwt-auth.guard';
export * from './local.strategy';
export * from './local-auth.guard';
export * from './auth.controller'; // this went from the top to the botttom

After making this change to the order, the application started right up.

If you like our content and want more tutorials, sign up for our monthly newsletter below. Or feel free to reach out to us on Twitter or via email with any questions.