Coder Social home page Coder Social logo

nestjs / event-emitter Goto Github PK

View Code? Open in Web Editor NEW
170.0 7.0 31.0 7.14 MB

Event Emitter module for Nest framework (node.js) ๐Ÿฆ‹

Home Page: https://nestjs.com

License: MIT License

JavaScript 3.07% TypeScript 96.15% Shell 0.77%
nestjs node nodejs events event-emitter typescript nest javascript

event-emitter's People

Contributors

caucik avatar drew-kimberly avatar kamilmysliwiec avatar maligosus avatar mathulbrich avatar matt1097 avatar micalevisk avatar nttestalert avatar pooreumu avatar renovate-bot avatar renovate[bot] avatar taj-p avatar thiagomini avatar tony133 avatar wodcz avatar zackdotcomputer 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  avatar  avatar

event-emitter's Issues

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:

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! ๐Ÿ˜„

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.

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

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)

EventEmitterModule crash with TypeError from reflect-metadata stack when used with Proxy

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

We have an AppModule that includes many modules. This is a bad interaction between two in particular:

  1. The EventEmitter module.
  2. A PrismaModule that uses the $extends function to add client features.

Strangely, when the factory function finishes adding the PrismaModule using the $extends function, the EventEmitter crashes with the following stack trace:

/Users/zack/code/learning/bug-repro/node_modules/reflect-metadata/Reflect.js:354
                throw new TypeError();
                      ^
TypeError: 
    at Reflect.getMetadata (/Users/zack/code/learning/bug-repro/node_modules/reflect-metadata/Reflect.js:354:23)
    at Reflector.get (/Users/zack/code/learning/bug-repro/node_modules/@nestjs/core/services/reflector.service.js:39:24)
    at EventsMetadataAccessor.getEventHandlerMetadata (/Users/zack/code/learning/bug-repro/node_modules/@nestjs/event-emitter/lib/events-metadata.accessor.ts:13:37)
    at EventSubscribersLoader.subscribeToEventIfListener (/Users/zack/code/learning/bug-repro/node_modules/@nestjs/event-emitter/lib/event-subscribers.loader.ts:76:29)
    at /Users/zack/code/learning/bug-repro/node_modules/@nestjs/event-emitter/lib/event-subscribers.loader.ts:59:18
    at MetadataScanner.scanFromPrototype (/Users/zack/code/learning/bug-repro/node_modules/@nestjs/core/metadata-scanner.js:34:31)
    at /Users/zack/code/learning/bug-repro/node_modules/@nestjs/event-emitter/lib/event-subscribers.loader.ts:55:30
    at Array.forEach (<anonymous>)
    at EventSubscribersLoader.loadEventListeners (/Users/zack/code/learning/bug-repro/node_modules/@nestjs/event-emitter/lib/event-subscribers.loader.ts:51:8)
    at EventSubscribersLoader.onApplicationBootstrap (/Users/zack/code/learning/bug-repro/node_modules/@nestjs/event-emitter/lib/event-subscribers.loader.ts:39:10)

This appears to be because Prisma's $extend function creates a Proxy object. Event-emitter tries to get the prototype of the proxied object, which returns the underlying class, and then get its keys. It then tries to iterate these keys on the Proxy and assumes they will all be defined. However, Proxy objects are free to redefine keys to be undefined or primitive values. When one of these is passed to reflect-metadata, it then crashes with this type error.

Minimum reproduction code

https://github.com/zackdotcomputer/nest-event-bugreport

Steps to reproduce

  1. npm i
  2. npm start:dev

Observe crash

Expected behavior

The startup process should not crash. Instead, if the event-emitter receives a result in its iteration that is neither an object nor a function, it should not pass it on to reflect-metadata.

Package version

2.0.2

NestJS version

10.2.7

Node.js version

18.18.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

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:

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

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.

Add OnSafeEvent

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

OnEvent has problem with server stops.

Describe the solution you'd like

import { applyDecorators, Logger } from '@nestjs/common';
import { OnEvent, OnEventType } from '@nestjs/event-emitter';
import { OnEventOptions } from '@nestjs/event-emitter/dist/interfaces';

function _OnSafeEvent() {
  return function (target: any, key: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;

    const metaKeys = Reflect.getOwnMetadataKeys(descriptor.value);
    const metas = metaKeys.map((key) => [key, Reflect.getMetadata(key, descriptor.value)]);

    descriptor.value = async function (...args: any[]) {
      try {
        await originalMethod.call(this, ...args);
      } catch (err) {
        Logger.error(err, err.stack, 'OnSafeEvent');
      }
    };
    metas.forEach(([k, v]) => Reflect.defineMetadata(k, v, descriptor.value));
  };
}

export function OnSafeEvent(event: OnEventType, options?: OnEventOptions | undefined) {
  return applyDecorators(OnEvent(event, options), _OnSafeEvent());
}

Teachability, documentation, adoption, migration strategy

No response

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

do not stop server when the exception not catched in OnEvent

Mitigating Event Loss Risk During NestJS Application Initialization

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

Problem Description:

In NestJS applications using the @OnEvent decorator, there's a risk of losing events emitted before the full completion of the application's bootstrap process. Specifically:

  • Early Emission: Events emitted before or during the onApplicationBootstrap lifecycle hook, including those from module constructors or onModuleInit, may go unnoticed because EventSubscribersLoader might not have completed setting up the listeners.
  • Post-Bootstrap Uncertainty: Even events fired immediately after the onApplicationBootstrap hook isn't guaranteed to be caught, as there's no assurance that all listeners are ready at this point.

This early emission problem threatens the reliability of applications relying on events for tasks like state initialization, startup procedures, or module communication. Ensuring all events are captured is crucial for maintaining consistent application behavior and avoiding missed operations or errors.

App Start
โ”œโ”€ Module Initialization
โ”‚  โ””โ”€ ๐Ÿšจ Potential Early Event Emission (Risk)
โ”‚  
โ”œโ”€ Application Bootstrap
โ”‚  โ”œโ”€ ๐Ÿšจ Another Potential Early Event Emission (Risk)
โ”‚  โ””โ”€ EventSubscribersLoader (onApplicationBootstrap)
โ”‚     โ””โ”€ Event Listeners Setup (๐Ÿ‘‚ Listening Starts)

Describe the solution you'd like

The solution involves several potential strategies:

  1. Deferred Event Emission: Implement a mechanism to defer the emission of events until it's guaranteed that all listeners are set up. This could involve queuing events emitted early and then releasing them once the application is fully bootstrapped.
  2. Lifecycle Hooks Enhancement: Enhance the order and timing of lifecycle hooks or the event listener setup process to ensure listeners are ready before any module emits an event.
  3. Documentation and Guidelines: Provide clear guidelines and best practices in the documentation to prevent early emission, possibly by outlining safe lifecycle phases for emitting events.

Teachability, documentation, adoption, migration strategy

  • Teachability: Update the NestJS official documentation to include guidelines and best practices for event handling, especially concerning the timing of event emissions and listener setup.
  • Documentation: Document the changes and new features in the NestJS release notes and update the API documentation to reflect any new methods or parameters.
  • Adoption: Encourage adoption by demonstrating the benefits of the new event handling strategies through examples and highlighting the potential pitfalls of early event emission.
  • Migration Strategy: Provide a clear and straightforward migration path for users to transition from the current event handling to the new method. Include any necessary code changes or steps to update their applications.

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

The motivation is to ensure reliable and consistent event handling in NestJS applications. Events are crucial for asynchronous tasks and inter-service communication. By ensuring that no events are lost due to timing issues related to application initialization, we improve the robustness, predictability, and reliability of applications. This change will benefit all NestJS users who rely on event-driven architecture, especially those building complex or modular applications where timing and order of initialization are critical.

Using event emitter in imported npm package cannot resolve emitter

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

Simply add a module that is included in a npm package to the app that contains a service that consumes the EventEmitter2 service.

This lead to this error

Error: Nest can't resolve dependencies of the PackageService (?). Please make sure that the argument EventEmitter at index [0] is available in the PackageModule context.

Instead, when I import the module directly it works as expected.

Minimum reproduction code

https://github.com/twilker/nest-event-bug-app

Steps to reproduce

  1. Clone Minimum reproduction code repository
  2. Execute on main branch to see wrong behavior
  3. Execute on working branch to see expected bahavior

Expected behavior

It should be possible to use it in npm packages as the purpose is to separate modules better by loose coupling. In order to facilitate the separation it is obvious to wish to split the nest app into multiple separately versioned npm packages and consume it in a single nest app.

Package version

1.4.2

NestJS version

9.4.3

Node.js version

18.12.1

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

Suppressing errors when updating from 2.0.0 to 2.0.1

Did you read the migration guide?

  • I have read the whole migration guide

Is there an existing issue that is already proposing this?

  • I have searched the existing issues

Potential Commit/PR that introduced the regression

f84ed00

Versions

2.0.0 > 2.0.1

Describe the regression

The following unit test should pass for the new 2.0.1 version.

Minimum reproduction code

class FakeSuccessfulEvent {
  constructor(readonly name: string) {}
}

class FakeFailedEvent {
  constructor(readonly name: string) {}
}

@Injectable({ scope: Scope.DEFAULT })
class FakeService {
  successCalled = false;
  failCalled = false;
  processed = false;

  constructor(private readonly publisher: EventEmitter2) {}

  async success(name = "fake"): Promise<void> {
    await this.publisher.emitAsync(FakeSuccessfulEvent.name, new FakeSuccessfulEvent(name));
    this.processed = true;
  }

  async fail(name = "fake"): Promise<void> {
    await this.publisher.emitAsync(FakeFailedEvent.name, new FakeFailedEvent(name));
    this.processed = true;
  }

  @OnEvent(FakeSuccessfulEvent.name)
  async handleSuccess(_event: FakeSuccessfulEvent): Promise<void> {
    this.successCalled = true;
  }

  @OnEvent(FakeFailedEvent.name)
  async handleFail(event: FakeFailedEvent): Promise<void> {
    this.failCalled = true;
    throw new Error(`Failed to handle event ${event.name}`);
  }
}

describe("EventEmitter", () => {
  let app: INestApplicationContext;
  let service: FakeService;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      providers: [FakeService],
      imports: [
        EventEmitterModule.forRoot({
          wildcard: true,
          delimiter: ".",
          verboseMemoryLeak: true,
        }),
      ],
    }).compile();

    app = await module.init();
    service = app.get(FakeService);
  });

  it("should successfully handle event", async () => {
    await service.success();
    expect(service.successCalled).toBe(true);
    expect(service.failCalled).toBe(false);
    expect(service.processed).toBe(true);
  });

  it("should fail when event isn't processed", async () => {
    await expect(service.fail("failed")).rejects.toThrow("Failed to handle event failed");
    expect(service.successCalled).toBe(false);
    expect(service.failCalled).toBe(true);
    expect(service.processed).toBe(false);
  });

  afterEach(async () => {
    await app.close();
  });
});

Expected behavior

To pass both unit tests (like it is when using v2.0.0). If suppressing errors is the new behavior, maybe the right way to go could be creating a minor/major version (to avoid breaking changes in a patch)

Other

No response

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

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

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

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)

Upgrade to use event emitter 3, or add an option for it

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

no

Describe the solution you'd like

Upgrade to use event emitter 3, or add an option for it

Teachability, documentation, adoption, migration strategy

No response

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

Event emitter 3 is faster, not use nodeJs event.

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

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

Option to throw error if an event fails to process

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

The new version of event-emitter 2.0.1 suppress all errors by default, as described here: #932. As the thread was closed, I'd like to suggest a way to keep the old behavior, because we can't update to the new version, since getting the errors when a event is unprocessed is crucial for us.

Describe the solution you'd like

It'd be nice if we can just include a property suppressErrors in EventEmitterModule or in OnEvent so it will be possible to get errors from failed listeners. Without that, probably we'll have to stuck with the 2.0.0 version.

Teachability, documentation, adoption, migration strategy

No response

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

The main goal is to get the erros thrown by the decorated OnEvent methods. This option could be deactivated by default (since the default now is to suppress all errors), but with an option to use the last behavior (suppressErrors: false), since that's very important for our projects.

async function constructor name not AsyncFunction

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

listenerFunction

    @OnEvent(TicketEventEnum.UPDATE, { async: true })
    async test() {
        console.error('test');
    }

eventemitter2

eventemitter.js

        if (promisify === undefined) {
          promisify = listener.constructor.name === 'AsyncFunction';
        }

the result

promisify is falseใ€‚listener is ticket.update (...args) => instance[methodKey].call(instance, ...args)
the .constructor.name === 'Function';

the problem reason

https://github.com/nestjs/event-emitter/blob/master/lib/event-subscribers.loader.ts#L95

this can cause emitAsync.catch not working !

Minimum reproduction code

https://github.com/nestjs/event-emitter/blob/master/lib/event-subscribers.loader.ts#L95

Steps to reproduce

No response

Expected behavior

listener constructor name is AsyncFunction

Package version

9.4

NestJS version

9.4

Node.js version

16

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

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

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 ๐Ÿ™๐Ÿป

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

[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

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",

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

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 21.6
  • cimg/node 21.6
npm
package.json
  • eventemitter2 6.4.9
  • @commitlint/cli 19.2.1
  • @commitlint/config-angular 19.1.0
  • @nestjs/common 10.3.7
  • @nestjs/core 10.3.7
  • @nestjs/platform-express 10.3.7
  • @nestjs/testing 10.3.7
  • @types/jest 29.5.12
  • @types/node 20.12.7
  • @typescript-eslint/eslint-plugin 7.6.0
  • @typescript-eslint/parser 7.6.0
  • eslint 8.57.0
  • eslint-config-prettier 9.1.0
  • eslint-plugin-import 2.29.1
  • husky 9.0.11
  • jest 29.7.0
  • lint-staged 15.2.2
  • prettier 3.2.5
  • reflect-metadata 0.2.2
  • release-it 17.1.1
  • rimraf 5.0.5
  • rxjs 7.8.1
  • ts-jest 29.1.2
  • typescript 5.4.4
  • @nestjs/common ^8.0.0 || ^9.0.0 || ^10.0.0
  • @nestjs/core ^8.0.0 || ^9.0.0 || ^10.0.0

  • 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.

@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)

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

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.