Search code examples
node.jstypescriptdependency-injectionnestjs

NestJS Repository seems to be injected but is in-fact empty?


I'm currently working on an API with NestJS and Sequelize, and it seems that there is a problem when injecting the repository. For context, when the service calls this.repo.findByKey the function is undefined and the program fails, but when inspecting with VSCode's debugger, the proptotype had the function inside of it.

Here is a reproduction of the source :

// service.ts
@Injectable()
export class Service {
  constructor(
    @Inject('REPOSITORY') private repo: IRepository
  ) {
    super();
  }

  async getByCode(code: string) {
    console.log(this.repo);                       >> [class Repository extends BaseRepository]
    console.log(this.repo.findByKey);             >> undefined

    return res = await this.repo.findByKey(code); >> this.repo.findByKey is not a function
  }
}

// repository.ts
@Injectable()
export class Repository
  extends BaseRepository
  implements IRepository
{
  constructor(
    @Inject('DATABASE_HELPER')
    databseHelper: DatabaseHelper,
    private mapper: CountryMapper,
  ) {
    super(databseHelper);
  }

  async findByKey(code: string) -> Promise<DTO> {
    ... never reached
  }
}

I cannot find the origim of this problem, is there a dark magician here to help me?

Per request, here is the module configuration :

@Module({})
export class ExampleModule {
  static register(typeClass: Type<IService>): DynamicModule {
    return {
      imports: [
        HelperModule,
        SequelizeModule.forFeature([Entity]),
      ],
      module: ExampleModule,
      providers: [
        ExampleMapper,
        {
          provide: 'REPOSITORY',
          useValue: Repository,
        },
        {
          provide: 'SERVICE',
          useClass: typeClass,
        },
      ],
      controllers: [Controller],
    };
  }
}

Solution

  • You are injecting the class itself. So this.repo is a constructor that never has been called.

            {
              provide: 'REPOSITORY',
              useValue: Repository,
            },
    

    useValue is suitable for shared values like config objects, connection strings, etc as the name imply.

    If you want to inject class instance you need to configure your provider like this

            {
              provide: 'REPOSITORY',
              useClass: Repository, // <-- notice useClass
            },