0

So, we need to implement a custom entity manager under the transaction function with typeorm. Why? Because we wrap the entity manager from typeorm and power it up with some custom function we needed.

@Injectable()
export class CustomEntityManager extends EntityManager implements IEntityManager {
  constructor(connection?: string) {
    super(getConnection(connection));
  }

  //#region CRUD methods

  async createOne<Entity, Dto extends CreateDto>(
    entity: EntityTarget<Entity>,
    dto: Dto,
    extraOptions?: ExtraOptions,
  ): Promise<Entity> {
    try {
      const _entity = this.create(entity, instanceToPlain(dto) as any);
      return await this.save(entity, _entity);
    } catch (err) {
      const entityName = extraOptions?.entityName || startCase((entity as Function).name);
      throw new CreateEntityException(entityName, err);
    }
  }
  // a lot of more functions

  customSoftDelete<Entity>(entity: EntityTarget<Entity>, criteria: any): Promise<UpdateResult> {
    try {
      return this.update(entity, criteria, { deleted: true } as any);
    } catch (e) {
      console.log(e);
      // @todo: open this error and check
      throw e;
    }
  }

  customTransaction<Entity>(
    runInTransaction: (entityManager: CustomEntityManager) => Promise<Entity>,
  ): Promise<Entity> {
    return super.transaction(runInTransaction);
  }

}

So, this is how our custom entity manager looks like. and now we are trying to use it ir order to soft delete some entities (before u say the typerom's soft delete is not working as we our needs)

  async deleteOne(id: Id): Promise<void> {
    const company = await this.findOneWithScopeOr404({ where: { id } });
    await this.manager.customTransaction(async (transactionManager) => {
      console.log(transactionManager);
      this.logger.log('removing company users');
      const userTransaction = await transactionManager.customSoftDelete(User, { companyId: company.id });
      this.logger.log(userTransaction);
    });
}

But when doing this, I thought that the transactionManager under the customTransaction was the "custom entity manager" but it wasn't. In compiling time there was no error but in runtime it was.. customSoftDelete wasn't a function of "entityManager" Is there anyway of modify this?

2
  • In your customTransaction : return super.transaction(runInTransaction); you are returning the Transaction manager from the parent class. You should be able to do return this.transaction no ? Commented Nov 15, 2022 at 17:13
  • I didn't understand what you mean. I won't able to return this.transacion.. Commented Nov 15, 2022 at 20:04

1 Answer 1

1

This is a possible solution, let me know if it works.

First there is no typing problem because you declared this here :

runInTransaction: (entityManager: CustomEntityManager) => Promise<Entity>,

But in reality typeorm Transaction has the following signature:

    async transaction<T>(
        runInTransaction: (entityManager: EntityManager) => Promise<T>,
    ): Promise<T>

When you call the method customTransaction, you are just returning the parent behavior so it's normal that the transactionManager is the parent (EntityManager).

However you can bypass this by using function bindings :

  customTransaction<Entity>(
    runInTransaction: (entityManager: CustomEntityManager) => Promise<Entity>,
  ): Promise<Entity> {
    return super.transaction(runInTransaction.bind(null, this)); // this equals to an instance of CustomEntityManager
  }

Sign up to request clarification or add additional context in comments.

1 Comment

Well, I based in your answer but replace this with an arrow function and it worked 100%!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.