GithubHelp home page GithubHelp logo

nestjs / event-emitter Goto Github PK

View Code? Open in Web Editor NEW
129.0 5.0 21.0 5.48 MB

Event Emitter module for Nest framework (node.js) πŸ¦‹

Home Page: https://nestjs.com

License: MIT License

JavaScript 3.99% TypeScript 95.00% Shell 1.00%
nestjs node nodejs events event-emitter typescript nest javascript

event-emitter's Introduction

Nest Logo

A progressive Node.js framework for building efficient and scalable server-side applications.

NPM Version Package License NPM Downloads Travis Linux Coverage Discord Backers on Open Collective Sponsors on Open Collective

Description

Events module for Nest built on top of the eventemitter2 package.

Installation

$ npm i --save @nestjs/event-emitter

Quick Start

Overview & Tutorial

Support

Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please read more here.

Stay in touch

License

Nest is MIT licensed.

event-emitter's People

Contributors

caucik avatar drew-kimberly avatar kamilmysliwiec avatar maligosus avatar matt1097 avatar micalevisk avatar nttestalert avatar renovate-bot avatar renovate[bot] avatar taj-p avatar thiagomini avatar tony133 avatar wodcz avatar

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  avatar

event-emitter's Issues

Using the event emitter inside an entity

I'm submitting a...


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

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

It's unclear how to emit an event from inside an entity. Or if this is possible at all. For example: I have a product and I want to decrement the inventory when someone buys it. product.adjustInventory(-1). I would like that function to emit an event incrementInventory, { oldAmount, newAmount, productId }. Is this possible? I want the product to be responsible for itself.

@OnEvent decorators is not working when applied multiple times on same method

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

Doing something like should work:

@Injectable()
class Service {

  @OnEvent('event.one')
  @OnEvent('event.two')
  private twoEventsOnOneMethod(data: any) {
    // ...
  }
}

As it should roughly translate to two .on calls on event emitter2:

eventEmitter2.on('event.one', () => service.twoEventsOnOneMethod)
eventEmitter2.on('event.two', () => service.twoEventsOnOneMethod)

But it doesn not. It only uses one of the OnEvent instead of all.

Minimum reproduction code

https://github.com/mentos1386/nestjs-events-on-event-issue

Steps to reproduce

  1. npm i
  2. npm start
  3. curl http://localhost:3000/

Expected behavior

In the logs, we would expect to see "hello from event one" and "hello from event two'. But only one will be present.

Package version

1.1.1

NestJS version

8.4.7

Node.js version

v16.15.1

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

Reference to issue that touches this topic #52 (comment)

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

circleci
.circleci/config.yml
  • cimg/node 19.6
  • cimg/node 19.6
npm
package.json
  • eventemitter2 6.4.9
  • @commitlint/cli 17.5.0
  • @commitlint/config-angular 17.4.4
  • @nestjs/common 9.3.12
  • @nestjs/core 9.3.12
  • @nestjs/platform-express 9.3.12
  • @nestjs/testing 9.3.12
  • @types/jest 29.5.0
  • @types/node 18.15.6
  • @typescript-eslint/eslint-plugin 5.56.0
  • @typescript-eslint/parser 5.56.0
  • eslint 8.36.0
  • eslint-config-prettier 8.8.0
  • eslint-plugin-import 2.27.5
  • husky 8.0.3
  • jest 29.5.0
  • lint-staged 13.2.0
  • prettier 2.8.6
  • reflect-metadata 0.1.13
  • release-it 15.9.1
  • rimraf 4.4.1
  • rxjs 7.8.0
  • ts-jest 29.0.5
  • typescript 5.0.2
  • @nestjs/common ^7.0.0 || ^8.0.0 || ^9.0.0
  • @nestjs/core ^7.0.0 || ^8.0.0 || ^9.0.0
  • reflect-metadata ^0.1.12

  • Check this box to trigger a request for Renovate to run again on this repository

Support eventemitter2.prependListener() as an alternative for registering subscribers

Is there an existing issue that is already proposing this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe it

I'd like to have some control over the ordering of event listeners. My general feature request is to provide an option such that I can ensure a given listener registered with the OnEvent decorator is fired before another listener.

Describe the solution you'd like

I'd like the OnEvent decorator options to support an interface similar to:

type OnEventOptions = OnOptions & { prependListener?: boolean }

prependListener will default to false. In EventSubscribersLoader, the new config value will be respected and register the decorated subscriber via:

  • on when prependListener is false
  • prependListener when prependListener is true

eventemitter2 ref: https://github.com/EventEmitter2/EventEmitter2#emitterprependlistenerevent-listener-options

Teachability, documentation, adoption, migration strategy

This feature will be backwards-compatible as the new configuration option is optional and defaults to false.

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

I'd like to ensure that a given decorator event subscriber is always triggered first.

Emit event decorator

Would be a great addition to have a decorator to emit an event, for example in a controller.

In staart/api, I have a decorator @AuditLog which is called like so:

@Controller('domains')
export class DomainController {
  constructor() {}
  @Post()
  @AuditLog('create-domain')
  async create() {
    return { ok: true }
  }
}

Similarly, we could do:

@Controller('domains')
export class DomainController {
  constructor() {}
  @Post()
  @EmitEvent('domain-created', new CreateDomainEvent())
  async create(): Promise<{ ok: boolean }> {
    return { ok: true }
  }
}

In this example, the event will be dispatched in the function doesn't throw an error. With this use case, I can replace my audit logger with an event emitter! πŸ˜„

Object null prototype error

Is there an existing issue for this?

  • I have searched the existing issues

nestjs/nest#226

Current behavior

Injecting object with null prototype into provider throw errors.

Expected behavior

Injecting object don't throwing errors, when use with @nestjs/event-emmiter.
I understand that eventEmitter scans all modules and providers imported into AppModule

Minimal reproduction of the problem with instructions

As a config file we use an ini file, and for parsing we use a simple module "ini-parser", but ini.parse return object with null prototype.

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

The error is very subtle. An exception was thrown when called

EventEmmiterModule.forRoot()

The fact that the problem is in the "Object null prototype", I realized only when I started to get into node_modules and use console.log there.

Minimum reproduction code

https://stackblitz.com/edit/nestjs-typescript-starter-uizvtp?file=src/app.module.ts

Steps to reproduce

  1. npm run start:dev

Expected behavior

Object injection must not throw an exception

I write possible solution this problem

let config = ini.parse(data as string) as Config;
// Null prorotype bug bypass
const configString = JSON.stringify(config);
config = JSON.parse(configString) as Config;
return config;

Package

  • I don't know. Or some 3rd-party package
  • @nestjs/common
  • @nestjs/core
  • @nestjs/microservices
  • @nestjs/platform-express
  • @nestjs/platform-fastify
  • @nestjs/platform-socket.io
  • @nestjs/platform-ws
  • @nestjs/testing
  • @nestjs/websockets
  • Other (see below)

Other package

@nestjs/event-emmiter

NestJS version

8.4.3

Packages versions

{
	"name": "frontend-server",
	"version": "0.0.1",
	"description": "",
	"author": "",
	"private": true,
	"license": "UNLICENSED",
	"scripts": {
		"prebuild": "rimraf dist",
		"build": "nest build",
		"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
		"start": "nest start",
		"migrate": "ts-node src/helpers/migrations/migrations.ts",
		"start:dev": "nest start --watch",
		"start:debug": "nest start --debug --watch",
		"scripts:create-test-license": "ts-node scripts/create-test-license.ts"
	},
	"dependencies": {
		"@nestjs/bull": "^0.5.4",
		"@nestjs/common": "^8.4.3",
		"@nestjs/core": "^8.4.3",
		"@nestjs/event-emitter": "^1.1.0",
		"@nestjs/platform-fastify": "^8.4.3",
		"@nestjs/schedule": "^1.0.2",
		"@nestjs/sequelize": "^8.0.0",
		"@types/pg": "^8.6.5",
		"bcryptjs": "^2.4.3",
		"bull": "^4.8.1",
		"date-fns": "^2.28.0",
		"fastify-secure-session": "^3.0.0",
		"ini": "^2.0.0",
	},
	"devDependencies": {
		"@nestjs/cli": "^8.2.4",
		"@nestjs/schematics": "^8.0.8",
		"@nestjs/testing": "^8.4.3",
		"@types/bcryptjs": "^2.4.2",
		"@types/bull": "^3.15.8",
		"@types/cron": "^1.7.3",
		"@types/express": "^4.17.13",
		"@types/ini": "^1.3.31",
		"@types/jest": "^27.4.1",
		"@types/lodash": "^4.14.180",
		"@types/node": "^16.11.24",
		"@types/nodemailer": "^6.4.4",
		"@types/supertest": "^2.0.12",
		"@typescript-eslint/eslint-plugin": "^5.16.0",
		"@typescript-eslint/parser": "^5.16.0",
		"eslint": "^8.12.0",
		"eslint-config-prettier": "^8.5.0",
		"eslint-plugin-prettier": "^4.0.0",
		"jest": "^27.5.1",
		"memfs": "^3.4.1",
		"prettier": "^2.6.1",
		"source-map-support": "^0.5.21",
		"supertest": "^6.2.2",
		"ts-jest": "^27.1.4",
		"ts-loader": "^9.2.8",
		"ts-node": "^10.7.0",
		"tsconfig-paths": "^3.14.1",
		"type-fest": "^2.12.1",
		"typescript": "^4.6.3"
	},
	"jest": {
		"moduleFileExtensions": [
			"js",
			"json",
			"ts"
		],
		"rootDir": "src",
		"testRegex": ".*\\.spec\\.ts$",
		"transform": {
			"^.+\\.(t|j)s$": "ts-jest"
		},
		"collectCoverageFrom": [
			"**/*.(t|j)s"
		],
		"coverageDirectory": "../coverage",
		"testEnvironment": "node",
		"moduleNameMapper": {
			"^src/(.*)": "<rootDir>/$1"
		}
	}
}

Node.js version

17.7.1

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

/home/almaz/omega-project-backend/frontend-server/node_modules/@nestjs/core/metadata-scanner.js:23
            yield* (0, iterare_1.iterate)(Object.getOwnPropertyNames(prototype))
TypeError: Cannot convert undefined or null to object
    at Function.getOwnPropertyNames (<anonymous>)
    at MetadataScanner.getAllFilteredMethodNames (/home/almaz/omega-project-backend/frontend-server/node_modules/@nestjs/core/metadata-scanner.js:23:50)
    at getAllFilteredMethodNames.next (<anonymous>)
    at new Set (<anonymous>)
    at MetadataScanner.scanFromPrototype (/home/almaz/omega-project-backend/frontend-server/node_modules/@nestjs/core/metadata-scanner.js:8:29)
    at /home/almaz/omega-project-backend/frontend-server/node_modules/@nestjs/event-emitter/dist/event-subscribers.loader.js:39:34
    at Array.forEach (<anonymous>)
    at EventSubscribersLoader.loadEventListeners (/home/almaz/omega-project-backend/frontend-server/node_modules/@nestjs/event-emitter/dist/event-subscribers.loader.js:36:14)
    at EventSubscribersLoader.onApplicationBootstrap (/home/almaz/omega-project-backend/frontend-server/node_modules/@nestjs/event-emitter/dist/event-subscribers.loader.js:25:14)
    at MapIterator.iteratee (/home/almaz/omega-project-backend/frontend-server/node_modules/@nestjs/core/hooks/on-app-bootstrap.hook.js:22:43)

EventEmitter.emit causes NestJs dependency engine to throw on runtime


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

Current behavior

There's a strange error with NestJs and its event emitter. I have an issue that if I remove an invokation of "emit" method in class A, then class B (which uses it) cannot be resolved Error: Nest can't resolve dependencies of the B (?, C) => A is unknown. When I add this line all works, when I comment it again everything fails.

This is strange, I know. Lack of declaration of method's invokation causes whole class to be undiscoverable by DI. Invokation doesn't take place (since class is not yet instatiated), but it's required for application to start.

When I change the event name it will also throw an error. So I need both invokation AND proper first string. Mystery to me.

I once had it my tests also (i.e. in one spec file). Test module compiled ok, but my test class couldn't be resolved.

I have lots of code in the same project that uses event emitter as both producers or consumers of events and I'm not experiencing similar issues.

Unfortunatelly I cannot provide a minimum repo, since this bug appears only in a specific case (but the same code fails on every machine) and I cannot give you the full code, because corporation would do some bad things to me.

Environment

I've used many minor versions of nest components, but always stick to major 6. Event emitter component was used in majors 0 and 1.
Currently I have:

"@nestjs-addons/in-memory-db": "^3.0.3",
"@nestjs/common": "^7.6.18",
"@nestjs/config": "^1.0.0",
"@nestjs/core": "^7.6.18",
"@nestjs/event-emitter": "1.0.0",
"@nestjs/platform-express": "^7.6.18",
"@nestjs/schedule": "^1.0.0",
"@nestjs/swagger": "^4.8.2",

Duplicate events when using useExisting providers

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

When defining providers with useExisting, any OnEvent handlers get registered multiple times with event-emitter

With the repo below, this is the console.log output:

Sending Event
Event Received [
'4e9f9082-5ad0-4c6d-84d1-8bd036a746e7',
'897c020e-7f77-4b6d-b298-579da9025cfe'
]
Event Received [
'4e9f9082-5ad0-4c6d-84d1-8bd036a746e7',
'897c020e-7f77-4b6d-b298-579da9025cfe'
]

This shows that the same event was received by the same object twice.

According to the documentation useExisting is only supposed to create an alias, I do not expect the service to start doing duplicate work.

Minimum reproduction code

https://github.com/matt1097/nestjs-event-issue

Steps to reproduce

  1. npm i
  2. npm run start
  3. send the REST call: http://127.0.0.1:3000/test
  4. Observe console output

Expected behavior

The following output is what is expected:

Sending Event
Event Received [
'4e9f9082-5ad0-4c6d-84d1-8bd036a746e7',
'897c020e-7f77-4b6d-b298-579da9025cfe'
]

Basically that the event was handled only once

Package version

1.3.0

NestJS version

9.0.8

Node.js version

14.19.3

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

I can get the expected behavior by modifying the forEach loop here: https://github.com/nestjs/event-emitter/blob/master/lib/event-subscribers.loader.ts#L49

if I add:

if (wrapper.isAlias) {
    return;
}

at the beginning of the foreach loop, it will skip registering the event handler a second time and I will get my expected behavior

EventEmitterModuleOptions maxListeners setting isn't applied

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

The code taken from the official guide doesn't seem to work for me.. I've got a config for eventing module

export const globalEventingConfig : EventEmitterModuleOptions = {
  global: true,
  wildcard: true,
  maxListeners: 32
}

Which is used in the module definition:

@Module({
  imports: [
    EventEmitterModule.forRoot(globalEventingConfig),
  ],
  providers: [
    EventEmitterService
  ]
})
export class AlPacinoModule { }

Yes, I still have memory leak warnings at startup: MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 ready listeners added to [Client]. Use emitter.setMaxListeners() to increase limit

What am I doing wrong? Thanks a mil!

Minimum reproduction code

https://github.com/singulart/

Steps to reproduce

nest start

Expected behavior

No warning is shown in logs

Package version

1.3.1

NestJS version

8.4.7

Node.js version

16.15.0

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

OnEvent decorator doesn't create listener in testing environment

I'm submitting a...


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

Current behavior

When trying to use the event emitter inside a TestingModule the OnEvent decorator doesn't add a listener.

Expected behavior

OnEvent should add the listener.

Minimal reproduction of the problem with instructions

describe('LoremService', () => {
  let service: LoremService;
  let eventEmitter: EventEmitter2;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [EventEmitterModule.forRoot()],
      providers: [LoremService],
    }).compile();

    service = module.get(LoremService);
    eventEmitter = module.get(EventEmitter2);
  });

  it('should perform some operation when user created', async () => {
    jest.spyOn(service, 'someOperation');

    await eventEmitter.emitAsync('user.created');
    // eventEmitter.hasListeners() returns false

    expect(service.someOperation).toHaveBeenCalled(); // test fails
  });
});
@Injectable()
export class LoremService {
  @OnEvent('user.created')
  async someOperation(): Promise<any> {
    // ...
  }
}

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

It should be possible to test that some logic is called when a certain event is triggered.

The documentation should be extended to describe how to write unit tests with the event emitter.

Environment


Nest version: 7.5.5

 
For Tooling issues:
- Node version: v12.18.0  
- Platform: Linux 

Others:

Injected EventEmitter2 in constructor is undefined

I'm submitting a...


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

Current behavior

Injected EventEmitter2 in constructor is undefined when used in a child module class

Expected behavior

It should be a EventEmitter2 instance everywhere (it should be global)

Minimal reproduction of the problem with instructions

Just inject EventEmitter2 in a service of a child module and do a console.log of it

Environment

Nest version: 7.5.2

Custom event decorators break with the latest array metadata type requirement

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

When using a custom event decorator an error is thrown: eventListenerMetadatas is not iterable. After digging it is clear that the latest release 1.4.1 and specifically this PR #657 causes it.

Minimum reproduction code

https://github.com/davidzwa/nest-event-bug/actions/runs/4292223946/jobs/7478397448

Steps to reproduce

  1. Create a custom decorator https://github.com/davidzwa/nest-event-bug/blob/main/src/custom-event.decorator.ts
  2. Register it https://github.com/davidzwa/nest-event-bug/blob/9d616087d86bac5adbe0fac929eb373e180572bf/src/app.service.ts#L6

See MR repo workflow for the error https://github.com/davidzwa/nest-event-bug/actions/runs/4292223946/jobs/7478397448

Expected behavior

The array type should either be enforced with the return type of the decorator (now using generic MethodDecorator) or preferably it should rather be backwards compatible and allow non-array event metadata to work without failure.

Undesirable alternative:
The error eventListenerMetadatas is not iterable should be prevented and clarified.

Takeaway: the return type at

return this.reflector.get(EVENT_LISTENER_METADATA, target);
is not enforced at build time.

Package version

1.4.1

NestJS version

^9.0.0

Node.js version

18.14.2

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

Provider EventEmitter can't not resolve when using TerserPlugin webpack

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

Build nestJS application with @nwrl/webpack using optimization: true. It'll change name of EventEmitter class name so DI container can't resolve this provider.
The root cause may be EventEmitter is a function not a class.

This is config of TerserPlugin of @nwrl/webpack

new TerserPlugin({
                parallel: true,
                terserOptions: {
                  keep_classnames: true,
                  ecma: 2020,
                  safari10: true,
                  output: {
                    ascii_only: true,
                    comments: false,
                    webkit: true,
                  },
                },
              })

Minimum reproduction code

none

Steps to reproduce

No response

Expected behavior

DI container can resolve EventEmitter provider

Package version

1.4.1

NestJS version

9.1.4

Node.js version

16.x

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

Missing dependency for Yarn 2 PnP

I'm submitting a...


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

Current behavior

Using the library with Yarn 2 PnP mode causes an error during run:

Error: @nestjs/event-emitter tried to access @nestjs/core, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.

Required package: @nestjs/core (via "@nestjs/core")

Expected behavior

Should run successfully.

Minimal reproduction of the problem with instructions

  1. Create a new project using nest new
  2. Convert the project to use Yarn 2 PnP (yarn set version berry)
  3. Add @nestjs/event-emitter to a blank project as per normal.
  4. yarn start:dev

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

So that it works with Yarn 2 PnP.

Environment


Nest version: 7.6.17

 
For Tooling issues:
- Node version: 15.9  
- Platform:  Linux 

Others:

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (github>whitesource/merge-confidence:beta)

[Question]: Get all Events

I'm submitting a...


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

Current behavior

I would like to have some kind of LoggingService that is able to catch all events that are emitted within my application. I correctly enabled wildcard in my EventEmitterModule on the top level.

Now i would like to catch all emitted events and store them within a database, like so:

@OnEvent('*')
  async logToDatabase(event: any) {
    console.log('logging event to database');
  }

However, the * wildcard does not catch events like user.created, because respective event has 2 blocks (user and created). In order to catch such events, the wildcard argument should be *.*.

However, if i use *.*, i would not be able to catch an event like user.attached.team or whatever.

Can we add a "real" wildcard that catches everything? Like, wouldn't it be better to have a * and a ? wildcard?

  • * catches everything - does not really matter how many blocks will follow. * will catch user.created but also user.attached.teams or shutdown. In turn, user.* will catch the user.created and user.attached.teams event.
  • ? will only work for one particular block, so ? will catch only events with one block length, like shutdown, whereas user.? will catch everything within user..

Thank you very much for your reply and suggestions

Make event name avaliable

Is there an existing issue that is already proposing this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe it

I'm trying to catch all my events and log them all by name and payload:

This gives undefined:

  @OnEvent("**")
  public handleEverything(parentId: number): void {
    // log all events by event name
    // @ts-expect-error this.event
    console.log(this.event)
  }

This doesn't get called:

  public constructor(private readonly eventEmitter: EventEmitter2) {
    this.eventEmitter.on("**", function (value1, value2) {
      // @ts-expect-error this.event
      console.log(this.event)
    })
  }

Describe the solution you'd like

Somehow have access to the event name.

Teachability, documentation, adoption, migration strategy

No response

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

Avoid lots of boilerplate.

Events are not emitted when I use "onModuleInit" for testing purposes

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

Events are not emitted when I use "onModuleInit" for testing purposes

@Injectable()
export class AppService implements OnModuleInit {
  constructor(private eventEmitter: EventEmitter2) {}

  onModuleInit() {
    this.getHello();
  }

  getHello(): string {
    const message = 'Emitting event in AppService->getHello()';
    console.log('get hello was trigged!');
    this.eventEmitter.emit('message', message);
    console.log(this.eventEmitter.listeners());
    return message;
  }

  @OnEvent('message')
  async onMessageReceived(payload: string) {
    console.log('showing payload', payload);
  }
}

The method "getHello" emits an event and this event is logged in the terminal. I am using "onModuleInit" for testing purposes and to check if everything is working but the event is not emitted when I use "onModuleInit". If I try to do a REST request to localhost:3000 everything works well!

Minimum reproduction code

https://github.com/felinto-dev/nestjs-event-emitter-issue

Steps to reproduce

  1. yarn
  2. yarn start:dev
  3. Check the terminal console
  4. Send a GET request to http://localhost:3000
  5. Check the terminal console
  6. Check the file src/app.service.ts to play around and debug this issue

Expected behavior

The event should be emitted no matter whether I use onModuleInit or send a REST API request.

Package version

1

NestJS version

8

Node.js version

16

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

Exceptions in async event handlers make the app crash

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

When an event handler is registered

  1. On an async method with @OnEvent('event')
  2. On a regular method with @OnEvent('event', {async: true})
  3. On an async method with @OnEvent('event', {async: true})

An unhandled exception in the event handler causes the app to exit

Minimum reproduction code

https://github.com/Babbiorsetto/nestjs-event-emitter-crash

Steps to reproduce

  1. npm i
  2. npm start:dev
  3. Open a shell and curl http://localhost:3000
  4. App crashes

Expected behavior

I expect the exception/Promise rejection to be caught and the app to not crash

Package version

1.3.1

NestJS version

9.2.0

Node.js version

16.18.0

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

The event listener is called twice.

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

Creating a standalone application calls the event listener multiple times.

Minimum reproduction code

https://github.com/boy672820/nest-event/blob/main/src/main.ts#L6

Steps to reproduce

No response

Expected behavior

const app = await NestFactory.create(AppModule);
const standalone = await NestFactory.createApplicationContext(AppModule);
const bupService = standalone.get(BupService);

bupService.subscribeTransfer();

Package version

^1.0.0

NestJS version

No response

Node.js version

No response

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

Allow providers with dynamic dependency trees to subscribe to events

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, it is not possible to add listeners to providers that do not have a static dependency tree:

.filter(wrapper => wrapper.isDependencyTreeStatic())

Expected behavior

It would be nice to be able to register event listeners in a non-static provider. Or make it explicit in docs that it won't work in providers with dynamic dependency trees.

Minimal reproduction of the problem with instructions

  • Create a provider with non-static dependency try (by injecting in it a request scoped provider for example).
  • Create a method decorated with OnEvent, as docs suggest, subscribing to a event.
  • Fire the event (it won't be handled).

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

I was trying to create a handler method in one of my resolvers that have a dataloader being injected into it. Due to the fact that dataloaders must be request scoped, this provider had a dynamic dependency tree, and the event handler was not being registered due to the logic mentioned above in the Current Behavior section.

I don't know if this was a expected behavior or a bug, so I marked it as a feature request, but I think this kind of hinders a little bit the usefulness of this package in a GraphQL scenario, as most resolvers will have a loader injected onto them making its dependency tree dynamic.

Environment


Nest version: 7.5.4
nest event emitter version: 0.0.2

 
For Tooling issues:
- Node version: 12.18.4  
- Platform: Windows

Jest Unit tests only emit events when intializing full AppModule

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

When I assemble aTestingModule which does not resemble the full AppModule, my event listeners don't get registered at the EventEmitter

With this code:

const module: TestingModule = await Test.createTestingModule({
      imports: [EventEmitterModule.forRoot()],
      providers: [RecipesService, EventEmitter2],
    }).compile()
   
const app = await module.createNestApplication();
await app.init();

the events don't work,

If I initialize the complete AppModule like this:

 const module: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

 const app = await module.createNestApplication();
 await app.init();

the events work fine.

this is my AppModule:

 @Module({
  imports: [
    EventEmitterModule.forRoot(),
    RecipesModule,
  ]
})
export class AppModule {}

Minimum reproduction code

Steps to reproduce

yarn test

Expected behavior

Events should be emitted and listened to in both scenarios

Package version

1.4.1

NestJS version

8.4.7

Node.js version

18.10.0

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

Multiple event types not handled (impossible to)

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

Passing an array to OnEvent does not work, and that might be intended behavior but is not mentioned anywhere in the docs.
That being said there is currently no way to handle multiple events using this module. Multiple @OnEvent would overwrite previous metadata.

The bug report #596 was just closed stating that indeed this does not work. (While using wildcards is viable in some cases, it is not in others)

Is this intentional and there is an important reason why this behavior is made impossible? Fixing this should be very simple, by simply changing the way metadata is stored to hold an array of settings, and on initialization walk the array. For less confusion in decorators and backwards compatibility, @OnEvents could be added, that would explicitly suggest that the array input will be treated as separate events. Should I open a PR for adding this functionality?

This is something that can be done in an hours time or less, and currently one needs to resort to:

@Injectable()
export class GenericListener implements OnApplicationBootstrap {
  constructor(
    private readonly eventEmitter: EventEmitter2,
  ) {}

  onApplicationBootstrap() {
    const callback = (event: EventData) =>
      this.handleGenericEvent(event);
    const events = [
      EVENT_ONE,
      EVENT_TWO
      EVENT_THREE,
    ];
    for (const event of events) {
      this.eventEmitter.on(event, callback);
    }
  }

Minimum reproduction code

provided in issue

Steps to reproduce

No response

Expected behavior

@OnEvents([
  EVENT_ONE,
  EVENT_TWO,
  EVENT_THREE,
])
async handleGenericEvent(event: EventData) {

or

@OnEvent(EVENT_ONE)
@OnEvent(EVENT_TWO)
@OnEvent(EVENT_THREE)
async handleGenericEvent(event: EventData) {

work as one would expect

Package version

master

NestJS version

No response

Node.js version

No response

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

Subscriber Trigger Multiple time on OnEvent Decorator

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

The Following Listener Triggered 2 Time on a single Emit

  @OnEvent('order.failed')   
  handleOrderFailed(payload: any) {
    console.log(payload);
  }

Where as the below works currectly,

@Injectable()
export class GlobalSubscriber {
  constructor(private eventEmitter: EventEmitter2) {
    this.eventEmitter.on('**', (payload) => {
      console.log(payload);
    });
  }

}

Seems BUG, please Verify

i chnaged OS, also run same in server ubuntu, but still it trigger 2 time, i getting console.log 2 time in console.

Minimum reproduction code

https://github.com/nestjs/nest/tree/master/sample/30-event-emitter

Steps to reproduce

npm i

Expected behavior

The Event Subscriber should trigger only 1 time, and not Multiple time

Package version

1.1.1

NestJS version

8.4.4

Node.js version

14+

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

Wrong behavior of @OnEvent decorator

I'm submitting a wrong behavior of @OnEvent decorator


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

Here i have simple class with subscribers and emitters.

@WebSocketGateway({path: '/api/ws', serveClient: false})
export class WebsocketGateway implements OnGatewayConnection<Socket>, OnGatewayDisconnect<Socket> {
    private online = 0

    @WebSocketServer()
    public readonly server: Server

    @Inject()
    private readonly eventEmitter2!: EventEmitter2

    async handleConnection(client: Socket, ...args: any[]) {
        this.online++
        this.eventEmitter2.emit(WsEvent.ConnectClient, client)
    }

    async handleDisconnect(client: Socket) {
        this.online--
        this.eventEmitter2.emit(WsEvent.DisconnectClient, client)
    }

    @OnEvent([WsEvent.ConnectClient, WsEvent.DisconnectClient])
    public emitOnlineUsers() {
        this.emit('online', this.online)
    }

    public emit(event: string, ...args: Array<any>) {
        this.server.emit(event, ...args)
    }
}

Expected behavior

I want to execute emitOnlineUsers() when one of ConnectClient or DisconnectClient fires. But i got nothing.

Current behavior

Array subscription via @OnEvent not working.

Minimal reproduction of the problem with instructions

Here another super simple examle.

@Module({
    imports: [
        EventEmitterModule.forRoot({}),
    ],
})
export class AppModule implements OnApplicationBootstrap {

    @Inject()
    private readonly eventEmitter2!: EventEmitter2

    onApplicationBootstrap() {
        setTimeout(() => this.eventEmitter2.emit('test1', 'test1'), 500)
        setTimeout(() => this.eventEmitter2.emit('test2', 'test2'), 700)
    }

    @OnEvent('test1')
    private singleSubscription(data: string) {
        console.log('singleSubscription', data)


    }

    @OnEvent(['test2'])
    private arraySubscription1(data: string) {
        console.log('arraySubscription1', data)
    }

    @OnEvent(['test1', 'test2'])
    private darraySubscription2(data: string) {
        console.log('arraySubscription2', data)
    }
}

Expected:

singleSubscription test1
arraySubscription2 test1
arraySubscription1 test2
arraySubscription2 test2

Got:

singleSubscription test1
arraySubscription1 test2

How to fix it

I think you should modify /lib/event-subscribers.loader.ts#58 to handle array in event variable.

  private subscribeToEventIfListener(
   instance: Record<string, any>,
   methodKey: string,
 ) {
   const eventListenerMetadata = this.metadataAccessor.getEventHandlerMetadata(
     instance[methodKey],
   );
   if (!eventListenerMetadata) {
     return;
   }
   const { event, options } = eventListenerMetadata;
   if (Array.isArray(event)) {
     for (const e of event) {
       this.eventEmitter.on(
           e,
           (...args: unknown[]) => instance[methodKey].call(instance, ...args),
           options,
       );
     }
   } else {
     this.eventEmitter.on(
         event,
         (...args: unknown[]) => instance[methodKey].call(instance, ...args),
         options,
     );
   }
 }

Environment


win 10
node v15.5.0
@nestjs/core 7.6.1
@nestjs/event-emitter 0.0.2

Feat: Add custom `EventEmitter2` implementation

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, an alternative implementation of EventEmitter2 cannot be provided

Expected behavior

I don't know if this feature is an scope of this package, but I think this could provide more flexibility.

Common Interface:

interface EventEmitter {
  emit(event: IEvent): boolean;
  ...
}

EventEmitter as injection token:

abstract class EventEmitter {}

EventEmitter default implementation:

class EventEmitter2 implements EventEmitter {
  ...
}

Provide a custom implementation:

{
  provide: EventEmitter2,
  useValue: options.custom(options) || new EventEmitter2(options),
},

FYI: I try to use my custom implemetation providing it like

{
  provide: EventEmitter2,
  useValue: MyEventEmitter2(options),
},

at AppModule but it means that listeners are not registered properly

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

In some cases, could be useful to use an alternative implementation of this class.

--

@kamilmysliwiec I wish know your thoughts in order to try an implementation πŸ™πŸ»

OnEvent decorator does not triggered if list of events provided

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

According to interface and docs decorator should accept string | symbol | Array<string | symbol>. It works fine if string provided for example @OnEvent(some.event). But it does not trigger if array was provided like : @OnEvent(['some.event1', 'some.event2']).

Minimum reproduction code

https://codesandbox.io/s/happy-ishizaka-d0gjsf

Steps to reproduce

check terminal view

Expected behavior

It should trigger function that was decorated with array

Package

  • I don't know. Or some 3rd-party package
  • @nestjs/common
  • @nestjs/core
  • @nestjs/microservices
  • @nestjs/platform-express
  • @nestjs/platform-fastify
  • @nestjs/platform-socket.io
  • @nestjs/platform-ws
  • @nestjs/testing
  • @nestjs/websockets
  • Other (see below)

Other package

@nestjs/event-emitter

NestJS version

No response

Packages versions

{
  "name": "nest-typescript-starter",
  "private": true,
  "version": "1.0.0",
  "description": "Nest TypeScript starter repository",
  "license": "MIT",
  "scripts": {
    "prebuild": "rimraf dist",
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  },
  "dependencies": {
    "@nestjs/common": "^9.0.0",
    "@nestjs/core": "^9.0.0",
    "@nestjs/event-emitter": "1.3.1",
    "@nestjs/platform-express": "^9.0.0",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^7.5.5"
  },
  "devDependencies": {
    "@nestjs/cli": "^9.0.0",
    "@nestjs/schematics": "^9.0.0",
    "@nestjs/testing": "^9.0.0",
    "@types/express": "^4.17.13",
    "@types/jest": "^28.1.4",
    "@types/node": "^18.0.3",
    "@types/supertest": "^2.0.12",
    "@typescript-eslint/eslint-plugin": "^5.30.5",
    "@typescript-eslint/parser": "^5.30.5",
    "eslint": "^8.19.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-prettier": "^4.2.1",
    "jest": "^28.1.2",
    "prettier": "^2.7.1",
    "source-map-support": "^0.5.21",
    "supertest": "^6.2.4",
    "ts-jest": "^28.0.5",
    "ts-loader": "^9.3.1",
    "ts-node": "^10.8.2",
    "tsconfig-paths": "^4.0.0",
    "typescript": "^4.7.4"
  },
  "jest": {
    "moduleFileExtensions": ["js", "json", "ts"],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "collectCoverageFrom": ["**/*.(t|j)s"],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }
}

Node.js version

No response

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

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.