question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow injectable entity subscribers

See original GitHub issue

I’m submitting a…


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

Currently only the default subscription mechanism of typeorm is usable. While this is a good thing, it does not allow to inject other services into the subscriber instance.

Expected behavior

By defining a new service class decorator, like @EntitySubscriber and the technique mentioned at https://github.com/typeorm/typeorm/issues/2630#issuecomment-447211212 we could implement a very easy way to implement rich subscribers which can participate in the nest injection container.

Minimal reproduction of the problem with instructions

I made a local solution myself which is straight forward, but works as expected:

// subscriber.decorator.ts
import { SetMetadata } from '@nestjs/common';

export const IS_SUBSCRIBER = 'IS_SUBSCRIBER';
export const Subscriber = () => SetMetadata(IS_SUBSCRIBER, true);
// app.module.ts (trimmed), guess this would be TypeORMModule.forRoot then

export class AppModule implements OnModuleInit {
  constructor(
    private readonly connection: Connection,
    private readonly container: ModulesContainer,
    private readonly reflector: Reflector,
  ) {}

  onModuleInit() {
    // find providers marked as entity subscribers...
    const subscribers = [...this.container.values()]
      .filter(({ providers }) => providers.size > 0)
      .reduce(
        (matching, { providers }) => [
          ...matching,
          ...[...providers.values()]
            .filter(
              provider =>
                provider.instance &&
                this.reflector.get(
                  IS_SUBSCRIBER,
                  provider.instance.constructor,
                ) === true,
            )
            .map(provider => provider.instance),
        ],
        [],
      );

    // ...and hand those instances over to typeorm
    subscribers.forEach(subscriber => {
      this.connection.subscribers.push(subscriber);
    });
  }
}

I'm pretty sure this kind of feature should be easily transported into the typeorm nest package.

What is the motivation / use case for changing the behavior?

Its allows nestjs dependency injection inside of entity subscribers. For example:

// user-subscriber.service.ts
@Subscriber()
@Injectable()
export class UserSubscriberService implements EntitySubscriberInterface {
  constructor(private readonly invitation: InvitationService) {}

  listenTo() {
    return User;
  }

  async beforeInsert(event: InsertEvent<User>) {
    const email = event.entity.email;
    const user = await event.manager.getRepository(User).findOne({
      where: {
        email,
      },
    });

    if (user !== undefined) {
      throw new BadRequestException(
        `User with email '${email}' already exists`,
      );
    }

    event.entity.status = UserStatus.UNREGISTERED;
    event.entity.password = null;
  }

  async afterInsert(event: InsertEvent<User>) {
    this.invitation.invite(event.entity);
  }
}

This provider is added to the module as usual. It actually works almost the same as websocket services.

Environment


Nest version: 6.1.1
Nest/TypeORM version: 6.0.0



Others:

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:15
  • Comments:13 (5 by maintainers)

github_iconTop GitHub Comments

17reactions
leesiongchancommented, Jan 1, 2020

Is there any chance to inject REQUEST object as well? I am struggling on implementing a BlameableColumn, anyone has any thoughts?

6reactions
LittleTheFucommented, May 3, 2020

I ran into the same problem.

Read more comments on GitHub >

github_iconTop Results From Across the Web

NestJS - Cannot inject a service into a subscriber
The only way I found to inject a dependency into a subscriber using NestJS, ... entities/revison.entity'; import { RevisionService } from '.
Read more >
Subscribers a.k.a Entity Listeners of TypeORM on NestJS
There's no documented way to do it but with the power of the Dependency Injection, we can achieve to get it injected by...
Read more >
Defining database subscribers | Vendure docs
By defining the subscriber as an injectable provider, and passing it to a Vendure plugin, you can take advantage of Nest's dependency injection...
Read more >
Understanding Method Injection - Manning
Take the following ApplyDiscountFor method of a Product Entity for example, ... Allows injecting Dependencies into data-centric objects that ...
Read more >
Database | NestJS - A progressive Node.js framework
To begin using the User entity, we need to let TypeORM know about it by inserting it into ... With that in place,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found