What's Changed
@nestjs/event-emitter is now a native ES module, and the major version is aligned with the Nest 12 release line (there is no 4.x — 3.1.0 goes straight to 12.0.0).
ESM migration
The package is published as pure ESM ("type": "module", compiled with NodeNext) behind a proper exports map. Deep imports into build internals (@nestjs/event-emitter/dist/...) are no longer resolvable — import from the package root.
// still the only supported entry point
import { EventEmitterModule, OnEvent } from '@nestjs/event-emitter';require(esm) — CommonJS still works
You do not need to convert your app to ESM. Thanks to Node's require(esm) support, a plain CommonJS Nest app can keep doing:
const { EventEmitterModule, OnEvent } = require('@nestjs/event-emitter');Both load paths are covered by a smoke test that runs against the built package in CI, so an interop regression fails the build rather than reaching npm.
Node.js requirement
engines.node is now >=20.19.0. That is the first Node 20 release with unflagged require(esm) (Node 22.12+ on the 22 line). On older runtimes a CommonJS app cannot require() this package at all.
Importing EventEmitter2
eventemitter2 is a CommonJS package, so under ESM Node cannot statically detect its named exports and import { EventEmitter2 } from 'eventemitter2' throws at load time. This package re-exports the class off the default export for you — import it from here instead:
import { EventEmitter2 } from '@nestjs/event-emitter';It is still exported as both a value and a type, so existing type annotations keep working.
Newly exported from the package root
EVENT_LISTENER_METADATA— the metadata key@OnEventwrites, so custom decorators can produce listener metadata the loader understands- the public interfaces (
EventEmitterModuleOptions,OnEventOptions,EventPayloadHost), which previously had to be reached through a deep import