I followed the controller-service-repository architecture and I want to use dependency inversion on StoneRepository. Having the code from bellow I get:
[Nest] 22656 - 03/21/2022, 5:01:44 PM ERROR [ExceptionsHandler] this.stoneRepository.getStones is not a function
What have I done wrong? Please help.
constants.ts
export const STONE_REPOSITORY_TOKEN = Symbol("STONE_REPOSITORY_TOKEN");
app.module.ts
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
import { StoneModule } from "./stone/stone.module";
@Module({
imports: [StoneModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
stone.module.ts
import { Module } from "@nestjs/common";
import { StoneController } from "./stone.controller";
import { StoneService } from "./stone.service";
import { StoneRepository } from "./stone.repository";
import { STONE_REPOSITORY_TOKEN } from "./constants";
@Module({
imports: [],
controllers: [StoneController],
providers: [
{
provide: STONE_REPOSITORY_TOKEN,
useValue: StoneRepository,
},
StoneService,
],
})
export class StoneModule {}
stone.controller.ts
import { Controller, Get } from "@nestjs/common";
import { StoneService } from "./stone.service";
import { Stone } from "./domain/Stone";
@Controller()
export class StoneController {
constructor(private stoneService: StoneService) {}
@Get("/stone")
async getStones(): Promise<Stone[]> {
return await this.stoneService.getStones();
}
}
stone.interface.repository.ts
import { Stone } from "./domain/Stone";
export interface StoneInterfaceRepository {
getStones(): Promise<Stone[]>;
}
stone.service.ts
import { Inject, Injectable } from "@nestjs/common";
import { StoneInterfaceRepository } from "./stone.interface.repository";
import { Stone } from "./domain/Stone";
import { STONE_REPOSITORY_TOKEN } from "./constants";
@Injectable()
export class StoneService {
constructor(
@Inject(STONE_REPOSITORY_TOKEN)
private stoneRepository: StoneInterfaceRepository,
) {}
async getStones(): Promise<Stone[]> {
return await this.stoneRepository.getStones();
}
}
stone.repository.ts
import { Injectable } from "@nestjs/common";
import { StoneInterfaceRepository } from "./stone.interface.repository";
import { Stone } from "./domain/Stone";
@Injectable()
export class StoneRepository implements StoneInterfaceRepository {
async getStones(): Promise<Stone[]> {
return Promise.resolve([new Stone()]);
}
}
You are using useValue
for the STONE_REPOSITORY_TOKEN
token's custom provider. This means that Nest will inject the direct reference, not the class instance, so you have no access to instance methods, like getStones()
. Change your module to this:
@Module({
imports: [],
controllers: [StoneController],
providers: [
{
provide: STONE_REPOSITORY_TOKEN,
useClass: StoneRepository,
},
StoneService,
],
})
export class StoneModule {}