I have a UserRepository
which handles creating/authenticating users infront of the database. I want to perform hashing & validation for the user's password, so I created a seperate service for that purpose, trying to follow single repsonsibility principle, which is declared like this:
@Injectable()
export default class HashService
And I import it in my module:
@Module({
imports: [TypeOrmModule.forFeature([UserRepository])],
controllers: [AuthController],
providers: [AuthService, HashService],
})
export class AuthModule {}
I wish to inject it into UserRepository
, I tried passing in it as a constructor parameter but it didn't work because it's base class already accepts 2 parameters there, so I tried injecting my service after them like so:
@EntityRepository(User)
export default class UserRepository extends Repository<User> {
constructor(
entityManager: EntityManager,
entityMetadata: EntityMetadata,
@Inject() private readonly hashService: HashService,
) {
super();
}
// Logic...
}
But hashService
was undefined, I also tried without the @Inject()
decorator.
What would be the best way to inject HashService
into my repository? Do I have to create a new instance of it?
Dependency injection is an inversion of control (IoC) technique wherein you delegate instantiation of dependencies to the IoC container (in our case, the NestJS runtime system), instead of doing it in your own code imperatively.
Repositories are classes or components that encapsulate the logic required to access data sources. They centralize common data access functionality, providing better maintainability and decoupling the infrastructure or technology used to access databases from the domain model layer. —
TypeORM Integration. For integrating with SQL and NoSQL databases, Nest provides the @nestjs/typeorm package. Nest uses TypeORM because it's the most mature Object Relational Mapper (ORM) available for TypeScript. Since it's written in TypeScript, it integrates well with the Nest framework.
Short answer: you don't.
TypeORM's custom repositories, repository classes, and entities are technically outside of Nest's DI system, so it's not possible to inject any values into them. If you really want to go about it, you can figure out what a Repository
class requires for it's constructor parameters and add them to a factory to instantiate the repository class and use it directly instead of via the TypeOrmModule.forFeature
, but that's quite a bit of extra work.
In my opinion, the custom repository pattern doesn't help too much in Nest, as services essentially hold the logic that the CustomRepository
would. The repository classes are your gateway to the database, but don't need any extra logic added to them.
You can add it manually from the module service like this:
askers.service.ts:
constructor(
@InjectRepository(AskersRepository)
private repository: AskersRepository,
private logger: LoggingService,
) {
this.repository.logger = logger;
}
askers.repository.ts:
logger: LoggingService;
And then the logger service will be available in the repository like it has been injected.
Here is an article I wrote about the hacking of injecting a service with request scope into TypeORM (© to me.. - 😉)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With