What would be the best way to inject custom repositories from typeorm using inversify. So far I came with 2 approaches:
Given a service that consumes a Repository:
@injectable()
export class EntityService {
private readonly _repo: EntityRepository;
constructor(@inject("entityRepo") repo: EntityRepository) {
this._repo = repo;
}
}
new class approach
Basically define a class that extends Repository:
@injectable()
export class EntityRepository extends Repository<Entity> {
constructor(@inject("entityManager") em: EntityManager) {
super(Entity, em);
}
}
// inversify.config
container.bind<EntityRepository>("entityRepo").to(EntityRepository);
extend repository (with factory)
More to declare, but as explained in the docs:
export type EntityRepository = Repository<Entity> & {
// custom operations declaration
}
export const repoFactory = (entityManager: EntityManager): EntityRepository => entityManager.getRepository(Entity).extend({
// define operations
});
// inversify.config
container.bind<EntityRepository>("entityRepo").toConstantValue(repoFactory(myDS.manager));
The first solution seems more elegant and shorter, but this is what happens when I need to handle transactions:
handling transactions
@injectable()
export class EntityService {
private readonly _repo: EntityRepository;
// constructor
doInTransaction() {
return this._repo.manager.transaction((trManager) => {
// only works with 'extend repository' method
const repo: EntityRepository = trManager.withRepository(this._repo);
// to work with 'new class', I have to do this
const repo: EntityRepository = new EntityRepository(trManager);
// all subsequent operations using 'repo' will be contained in a transaction.
}
}
}
What is the preferred approach?
Given these 2 solutions, which one is preferred? The first gives control over the instantiation of the repository, but the transactional issue means manually creating a new instance. The second option relies on a singleton (constant) repository.