Giter Club home page Giter Club logo

nest_transact's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

nest_transact's Issues

Error in import of library

The version 1.1.2 throws me the error:

Error: Cannot find module '/var/server/node_modules/nest-transact/index.js'. Please verify that the package.json has a valid "main" entry
    at tryPackage (internal/modules/cjs/loader.js:295:19)
    at Function.Module._findPath (internal/modules/cjs/loader.js:508:18)
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:802:27)
    at Function.Module._load (internal/modules/cjs/loader.js:667:27)
    at Module.require (internal/modules/cjs/loader.js:887:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/var/server/dist/modules/benefits/benefits.service.js:34:25)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32) {
  code: 'MODULE_NOT_FOUND',
  path: '/var/server/node_modules/nest-transact/package.json',
  r

Reverting to 1.0.2 got rid of the problem, the problem seems to be that there isn't any index.js in that published version of the library

nest-transact doensn't seem to work well with custom repository

Hi, when I try to use it with custom repostiories, I get error saying cannot get undefined of whichever method I tried to call with custom repository

I decorated my custom repository with @entityrepository and imported with TypeOrmModule.forFeature in my module where I declared custom repository

Is there anything more I should do to make it work?

I made repository for reproducing errors here

Crash in `getArgument`

I have a service that depends on a service that uses the HttpModule for external API communication. This caused a problem with this library.

The problem is that the repository detection is a bit naive. Currently it decides the dependency is a Repository if the it is a string, but other dependencies may be string at this point as well, like the HttpModule.

  private getArgument(param: string | ClassType, manager: EntityManager): any {
    let argument: Repository<any>;
    const id = typeof param === 'string' ? param : param.name;
    if (this.cache.has(id)) {
      return this.cache.get(id);
    }
    if (typeof param === 'string') {
      const repository: Repository<any> = this.moduleRef.get(param, { strict: false });

      const entity: any = repository.metadata.target; // crash! target is not a property of undefined

      argument = manager.getRepository(entity);
    } else {
      argument = this.findArgumentsForProvider(param as ClassType, manager);
    }
    this.cache.set(id, argument);
    return argument;
  }

I was able to fix this by adding a instanceof Repository check, to make sure that we have an actual TypeORM before we access it's metadata that might not be there.

   private getArgument(param: string | ClassType, manager: EntityManager): any {
    let argument: Repository<any>
    const id = typeof param === 'string' ? param : param.name

    if (this.cache.has(id)) {
      return this.cache.get(id)
    }

    if (typeof param === 'string') {
      // Fetch the depedency.
      const depedency: Repository<any> = this.moduleRef.get(param, { strict: false })

      if (depedency instanceof Repository) {
        // If the dependency is a repository, make a new repository with the desired transaction manager.
        const entity: any = depedency.metadata.target
        argument = manager.getRepository(entity)
      } else {
        // The dependency is not a repository, use it directly.
        argument = depedency
      }
    } else {
      argument = this.findArgumentsForProvider(param as ClassType, manager)
    }
    this.cache.set(id, argument)
    return argument
  }

And now I believe it seems to working as intended.

Thanks for this code. It's an elegant solution to a tricky problem and this has been super helpful!

Known work-arounds for custom repositories inside a transaction?

I cannot find a way to make custom repositories work inside a transaction.

Since v9.0.0 of @nestjs/typeorm and v0.3.0 of typeorm you can not create custom repositories with class style, like it showed below:

this notice says it's not possible I think - but I can't be sure if it's not be done elsewhere? Do you know of any solution?

Question : Is `nest_transact` working with chain of services ?

Hi :)

Thanks for this useful repo in order to improve the experience of transactions in NestJS application. Your solution is very nice in order to avoid transmitting entityManager in each services' call and also in order to avoid using Transactional Typeorm decorators which will be depreciated in the future.

However is your solution forwarding entityManager through a chain of services ?

class Controller {
  someAction() {
    return getManager().transaction((entityManager) => {
      return this.parentService.withTransaction(entityManager).someParentMethod();
  }
}

class ParentService {
  someParentMethod() {
    return this.childService.someChildMethod();
    // Do we have to use `withTransaction` here ? 
    // How to access `entityManager` ?
  }
}

class ChildService {
  someChildMethod() {
    return this.childRepo.someRepoMethod();
  }
}

Custom repository is not generated

Hi,
I just had a case where I injected a custom repository into a service. There also is another injected class which also uses this repository, like this:

//repository.ts
@EntityRepository(MyEntity) 
export class MyRepository extends Repository<MyEntity> {
//...custom methods
}

//service.ts
export class MyService extends TransactionFor<MyService> {
  constructor(
    private myRepository: MyRepository,
    private myOtherClass: MyOtherClass,
    moduleRef: ModuleRef
  ) {
    super(moduleRef);
  }

  //...methods using myRepository      
}

//my-other-class.ts
@Injectable()
export class MyOtherClass {
  constructor(
    private myRepository: MyRepository
  )
}

When nest-transact 1.1.3 creates new repositories, it actually sees that there is a custom repository, but does not generate a new repository with the custom methods:

//line 64
argument = manager.getRepository(entity);

If this line is changed to

argument = isCustomRepository ? manager.getCustomRepository(param as any) : manager.getRepository(entity);

then it seems to actually generate a new repository with the custom method.

Services get pulled in as Entity element in transaction

Description

Please see the code below, I've tried to debug this problem, but I was unsuccessful. Any help is much appreciated

Error stacktrace:

UnknownElementException [Error]: Nest could not find UsersService element (this provider does not exist in the current context)
    at InstanceLinksHost.get (/Users/repos/api/node_modules/@nestjs/core/injector/instance-links-host.js:15:19)
    at Object.find (/Users/repos/api/node_modules/@nestjs/core/injector/module-ref.js:39:55)
    at Object.get (/Users/repos/api/node_modules/@nestjs/core/injector/module.js:350:28)
    at UsersService.getArgument (/Users/repos/api/node_modules/nest-transact/dist/lib/with-transaction.js:31:35)
    at /Users/repos/api/node_modules/nest-transact/dist/lib/with-transaction.js:83:43
    at Array.forEach (<anonymous>)
    at UsersService.findArgumentsForProvider (/Users/repos/api/node_modules/nest-transact/dist/lib/with-transaction.js:79:14)
    at UsersService.getArgument (/Users/repos/api/node_modules/nest-transact/dist/lib/with-transaction.js:71:29)
    at /Users/repos/api/node_modules/nest-transact/dist/lib/with-transaction.js:83:43
    at Array.forEach (<anonymous>) 

Controller code

@ApiTags('Users')
@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService, private readonly dataSource: DataSource) {}

  @Post('create-user')
  @ApiOperation({
    summary: 'Role: open. Creates: User, User.stripe, User.inventory for all itemTypes, User.address',
    description: 'Creates user. For address please enter both types of address: bill_to and ship_to.',
  })
  @ApiBody({ type: CreateUserDto, required: true })
  @ApiResponse({ type: Boolean, status: 201 })
  async create(@Body() createUserDto: CreateUserDto): Promise<boolean> {
    return await this.dataSource.transaction(manager => this.usersService.withTransaction(manager).create({ createUserDto }));
  }
} 

Service code:

@Injectable()
export class UsersService extends TransactionFor<UsersService> {
  private readonly logger = new Logger(UsersService.name);

  constructor(
    private readonly eventEmitter: EventEmitter2,
    private readonly paymentService: PaymentService,
    private readonly eventStore: EventStore,
    private readonly inventoryService: InventoryService,
    private readonly encryptionService: EncryptionService,
    private readonly itemService: ItemService,
    @InjectRepository(UserEntity)
    private readonly userRepository: Repository<UserEntity>,
    moduleRef: ModuleRef,
  ) {
    super(moduleRef);
    this.registerAdmin();
  }

  async create({ createUserDto }: { createUserDto: CreateUserDto }): Promise<boolean> {
    let stripeId: string;
    try {
      const newUser = new UserEntity();
      for (const key in createUserDto) {
        newUser[key] = createUserDto[key];
      }
      newUser.password = await this.encryptionService.encrypt({ password: createUserDto.password });
      newUser.stripe = await this.paymentService.createStripeAccount({ newUser });
      stripeId = newUser.stripe.id;
      newUser.magicToken = [];
      newUser.magicToken.push(crypto.randomBytes(30).toString('hex'));

      const inventories = await this.inventoryService.addInventoryToEntity({ user: newUser });
      newUser.inventories = [];
      for (const inventory of inventories) {
        newUser.inventories.push(inventory);
      }

      await this.userRepository.save(newUser);
      this.logger.log(`New User ${newUser.id} created.`);
      this.eventEmitter.emit(Events.UserRegistered, new UserRegisteredEvent(newUser.email, newUser.magicToken[0]));
      await this.eventStore.appendEvent(newUser, new CreateUserEvent({ id: newUser.id }, createUserDto));
      return true;
    } catch (err) {
      this.logger.error(err);
      await this.paymentService.deleteStripeAccount({ stripeId });
      throw err;
    }
  }
}

Cannot resolve ids of forwardRefs

When a service has a forwardRef in its constructor, the id is undefined. Attempting to create a transactional service with a forwardRef results in an error when the id is scanned if it is a repository:

TypeError: Cannot read property 'includes' of undefined
    at SomeService.getArgument (/path/to/application/node_modules/nest-transact/lib/with-transaction.ts:47:32)
//... rest of the stack trace

Example for a service with forwardRefs:

@Injectable()
export class SomeService extends TransactionFor<SomeService> {
  constructor(
    @InjectRepository(SomeRepository)
    private readonly someRepository: SomeRepository,
    @Inject(forwardRef(() => SomeOtherClass))
    private someOtherClass: SomeOtherClass,
    moduleRef: ModuleRef,
  ) {
    super(moduleRef);
  }
}

The object in this case is a ForwardReference (provided by @nestjs/common), so one could get the forwardRef function of that object, execute it, and get the id by its name, for example.

Unable to read env variables from config service.

There is a config service that I have configured to use @nestjs/config module underneath. Whenever this config service is injected, I no longer can get the config variables from the service when one of the services is inheriting from the TransactionFor class.

Is it possible to back port the "null dependency" fix (PR #14) into `v8.0.0`

Thanks for providing this library.

I have a project that I can not yet upgrade to v9.0.1 and I am blocked using the v8.0.0 dues to the "null dependency" issue fixed by #14.

Is it possible to back port the fix and publish it as v8.0.1?

If you create a branch v8.0.x branch (from the v8.0.0 tag) I could create a PR with the fix (from #14) for you to check and publish from the v8.0.x branch).

FYI: The issue occurs when I use @Inject('SOME_STRING') someThing: SomeClass. In this case the param is a string that is not canBeRepository so dependency is never set.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.