DaCurse
DaCurse

Reputation: 825

How do you inject a service in NestJS into a typeorm repository?

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?

Upvotes: 13

Views: 12199

Answers (3)

Israel
Israel

Reputation: 1454

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.. - 😉)

Upvotes: 1

KielSoft
KielSoft

Reputation: 433

You may also assign an instance of particular service from main service that instantiate the repository.

i.e.

A. catalog.service.ts

@Injectable()
export class CatalogService {
    constructor (
        private readonly cacheService: CacheService,
        public readonly catalogRepository: CatalogRepository
    ) {
        this.catalogRepository.cacheService = this.cacheService;
    }
}

B. catalog.repository.ts

@EntityRepository(CatalogEntity)
export class CatalogRepository extends Repository<CatalogEntity> {
    cacheService: CacheService;
    cacheExpirySeconds = 60*60;
}

Upvotes: 0

Jay McDoniel
Jay McDoniel

Reputation: 70151

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.

Upvotes: 13

Related Questions