odavid / typeorm-transactional-cls-hooked

A Transactional Method Decorator for typeorm that uses cls-hooked to handle and propagate transactions between different repositories and service methods. Inpired by Spring Trasnactional Annotation and Sequelize CLS
MIT License
522 stars 86 forks source link

Support the latest version of typeorm (v0.3.x) #107

Open micalevisk opened 2 years ago

micalevisk commented 2 years ago

even tho the peer dep semver range allows the usage of typeorm@^0.3.0, maybe few deprecations & drops on the latest version of typeorm could break typeorm-transactional-cls-hooked@0.1.21

https://github.com/odavid/typeorm-transactional-cls-hooked/blob/c16e19f1727e3e55832848a4e135cc19fb7160fb/package.json#L63-L65

Please, read this when you have time: https://github.com/typeorm/typeorm/releases/tag/0.3.0 ~And close this Issue when you confirm that we can use your package with the latest version of typeorm. I can't find this out by myself yet.~

Jedliu commented 2 years ago

Just made a simple test that showed it's not working because no connection could be found. Looking forward to the update. Thank you!

ondrakub commented 2 years ago

any progress?

ymchun commented 2 years ago

since the getConnection is deprecated, we need to find a way to pass the connection to the hook

https://github.com/typeorm/typeorm/pull/8616

raethlo commented 2 years ago

Hey, are there any updates on this? nestjs has already released support for 0.3. recently https://github.com/nestjs/typeorm/pull/1233 in @nestjs/typeorm.

hygo2025 commented 2 years ago

Hey, are there any updates on this?

jczacharia commented 2 years ago

A possible solution I found was to add to the Transactional.ts file with the NestJS Inject decorator like so:

import { Inject } from '@nestjs/common'
import { DataSource } from 'typeorm'
import { Options, wrapInTransaction } from './wrapInTransaction'

/**
 * Used to declare a Transaction operation. In order to use it, you must use {@link BaseRepository} custom repository in order to use the Transactional decorator
 * @param connectionName - the typeorm connection name. 'default' by default
 * @param propagation - The transaction propagation type. see {@link Propagation}
 * @param isolationLevel - The transaction isolation level. see {@link IsolationLevel}
 */
export function Transactional(options?: Options): MethodDecorator {
  return (target: any, methodName: string | symbol, descriptor: TypedPropertyDescriptor<any>) => {
    Inject(DataSource)(target, '__data_source_key__')
    const originalMethod = descriptor.value
    descriptor.value = wrapInTransaction(originalMethod, { ...options, name: methodName })

    Reflect.getMetadataKeys(originalMethod).forEach((previousMetadataKey) => {
      const previousMetadata = Reflect.getMetadata(previousMetadataKey, originalMethod)
      Reflect.defineMetadata(previousMetadataKey, previousMetadata, descriptor.value)
    })

    Object.defineProperty(descriptor.value, 'name', { value: originalMethod.name, writable: false })
  }
}

Then in the wrapInTransaction.ts file you can access it like so: const dataSource: DataSource = (this as any)?.['__data_source_key__'];

However, after doing this only the test_nestjs.ts file passes and the test_simple.ts does not.

I'll keep working on this and try to get a PR but maybe this will help someone else figure it out faster.

EDIT:

If you want to try it out:

  "typeorm-transactional-cls-hooked": "git+https://github.com/jczacharia/typeorm-transactional-cls-hooked.git",

use in your package.json

sadiqumar20 commented 2 years ago

this works for me.

yookky commented 2 years ago

A possible solution I found was to add to the Transactional.ts file with the NestJS Inject decorator like so:

import { Inject } from '@nestjs/common'
import { DataSource } from 'typeorm'
import { Options, wrapInTransaction } from './wrapInTransaction'

/**
 * Used to declare a Transaction operation. In order to use it, you must use {@link BaseRepository} custom repository in order to use the Transactional decorator
 * @param connectionName - the typeorm connection name. 'default' by default
 * @param propagation - The transaction propagation type. see {@link Propagation}
 * @param isolationLevel - The transaction isolation level. see {@link IsolationLevel}
 */
export function Transactional(options?: Options): MethodDecorator {
  return (target: any, methodName: string | symbol, descriptor: TypedPropertyDescriptor<any>) => {
    Inject(DataSource)(target, '__data_source_key__')
    const originalMethod = descriptor.value
    descriptor.value = wrapInTransaction(originalMethod, { ...options, name: methodName })

    Reflect.getMetadataKeys(originalMethod).forEach((previousMetadataKey) => {
      const previousMetadata = Reflect.getMetadata(previousMetadataKey, originalMethod)
      Reflect.defineMetadata(previousMetadataKey, previousMetadata, descriptor.value)
    })

    Object.defineProperty(descriptor.value, 'name', { value: originalMethod.name, writable: false })
  }
}

Then in the wrapInTransaction.ts file you can access it like so: const dataSource: DataSource = (this as any)?.['__data_source_key__'];

However, after doing this only the test_nestjs.ts file passes and the test_simple.ts does not.

I'll keep working on this and try to get a PR but maybe this will help someone else figure it out faster.

EDIT:

If you want to try it out:

  "typeorm-transactional-cls-hooked": "git+https://github.com/jczacharia/typeorm-transactional-cls-hooked.git",

use in your package.json

I can add to your solution how not to use BaseRepository

patchRepositoryManager(DataSource.prototype)

and inside code

const repo = dataSource.getRepository(UserEntity);

mahns1201 commented 2 years ago

Is this why "ERROR [ExceptionHandler] Class constructor repository cannot be invoked without 'new'" occurs when using BaseRepository in "type-transactional-cls-hooked@0.1.21"?

my version is this "typeorm": "^0.3.6" "@nestjs/typeorm": "^8.1.3"

so, i use CustomRepository on entity.ts like this. @CustomRepository(User) export class UserRepository extends BaseRepository {}

at that time this Error occur.

export class UserRepository extends Repository {} it does not occur any Error.

i already tried to change my tsconfig.json file's compilerOptions but it doesn't work. 🥲

Mcheikh2 commented 2 years ago

Any updates ?

xtrinch commented 2 years ago

The above code from @jczacharia works for me, with one addition (No need to extend the base repo from this lib this way): patchRepositoryManager(Repository.prototype) after initializeTransactionalContext() You can then do this.somethingRepo.find(...) like you normally would with the usage of the decorator

Aliheym commented 2 years ago

Hi guys, thanks a lot to the author for such a great library. But I'm really sorry that the lib hasn't support last TypeORM changes.

I needed this library functionality for my new project but with support of newer versions of TypeORM, so I made a fork of this library and did necessary changes and improvements. I also made a package for easy use in my project.

If it helps anyone, you can take a look: https://github.com/Aliheym/typeorm-transactional

H4ad commented 2 years ago

Hey @odavid, @Aliheym's solution still keeps the original library design but creates a breaking change, rather than trying to keep two libraries, why not @Aliheym create a merge in this library with your modifications?

Also, maybe you can share the maintainer responsibilities so that it doesn't overwhelm you too much, what do you think?

Aliheym commented 2 years ago

It will be cool.

ckawell-sb commented 2 years ago

The TLDR (am I getting this right?): This npm package is no longer being updated (per the latest PR's comment), but there is a forked npm package that is updated: https://www.npmjs.com/package/typeorm-transactional

Caesarsage commented 1 year ago

Can i use @Aliheym package and this together ? Like i already have a codebase with this package or i can use @Aliheym and unistall without causing code breaks ? Seems this package have been abandon