v6.x → v7.x
The v7 major version ships each package as both an ES module and a CommonJS build (see Module format). Node picks the right one based on whether the package is imported or required.
There are no changes to the API or to the behavior, and for the vast majority of applications the upgrade is a version bump with no code changes.
Dropped support for Node 20
Node 20 reached its end of life on 2026-04-30, the packages now require Node 22 or newer (the engines field moved >=22)
All packages got new major versions
This is a repo-wide major version bump. All @nestjs-cls/* packages are released as new majors together with the core package, so upgrade them in one go:
| package | version |
|---|---|
nestjs-cls | v7.x |
@nestjs-cls/transactional | v4.x |
@nestjs-cls/transactional-adapter-* | v2.x |
Deep imports are no longer possible
The packages now declare an exports field in their package.json, which only exposes the package root. At the same time, the build output moved from dist/src to dist/cjs and dist/esm.
If you imported an internal file directly, for example:
import { ClsService } from 'nestjs-cls/dist/src/lib/cls.service';
Node now fails with ERR_PACKAGE_PATH_NOT_EXPORTED. Import from the package root instead:
import { ClsService } from 'nestjs-cls';
If something you need is not exported from the root, please open an issue.
The CLS_* symbols are now registry symbols
CLS_ID, CLS_REQ, CLS_RES and CLS_CTX are created with Symbol.for('nestjs-cls:<NAME>') instead of Symbol('<NAME>'), so that both copies (CJS and ESM) of the package use the same store keys and avoid the "dual package hazard" and losing context.
Use the exported constants as before. The only visible difference is the symbol's description, e.g. CLS_ID.description is now 'nestjs-cls:CLS_ID' instead of 'CLS_ID', which only matters if you asserted on it somewhere.