chore: prep for NestJS 12 (deep-import removal, dual ESM/CJS, Vitest)#509
chore: prep for NestJS 12 (deep-import removal, dual ESM/CJS, Vitest)#509drieshooghe wants to merge 2 commits into
Conversation
Replace `@nestjs/core/injector/*` deep imports with the public `DiscoveryService` API so the lib survives NestJS 12's CJS→ESM transition and stricter `exports` maps. Centralize the wrapper type as `ProviderWrapper` (sourced from `DiscoveryService['getProviders']`) and route the buses/event-map through it. Ship both ESM (`dist/index.mjs`) and CJS (`dist/index.js`) from every publishable package via tsup, with a condition-specific `exports` map and dual `.d.mts`/`.d.ts` declarations. Add the missing `@nestjs/common` peer dep on every integration package. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Jest+@swc/jest can't load ESM-only @nestjs/* packages without convoluted transformIgnorePatterns. Vitest natively understands ESM, which is where the NestJS toolchain is heading per the v12 roadmap. This unblocks the v12 bump. - Drop jest, @swc/jest, @types/jest, jest-mock; add vitest, @vitest/coverage-v8, unplugin-swc (handles decorator metadata). - Replace each packages/*/jest.config.js with vitest.config.mts; shared base at packages/config/vitest/base.mjs (.mjs so it loads natively under Node ESM alongside Vite 7). - Move Jest moduleNameMapper aliases to Vite resolve.alias. - Convert spec files: jest.fn → vi.fn, jest.spyOn → vi.spyOn, jest.useFakeTimers/useRealTimers → vi equivalents, jest.Mocked<T> → Mocked<T> from 'vitest'. - packages/testing/e2e/e2e-suite.ts: switch its lone jest.fn() to vi.fn(). - Add "types": ["node", "vitest/globals"] to package tsconfigs so describe/ it/expect/vi are typed without per-file imports. - Drop the broken test:cov:check script (shell-quoted JSON never worked); threshold enforcement now lives in the shared vitest config. - Update .npmignore entries from jest.config.js to vitest.config.mts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #509 +/- ##
==========================================
- Coverage 90.93% 90.41% -0.52%
==========================================
Files 98 98
Lines 2217 2024 -193
Branches 531 529 -2
==========================================
- Hits 2016 1830 -186
+ Misses 80 74 -6
+ Partials 121 120 -1
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Summary
Lays the groundwork so the eventual NestJS 11 → 12 bump becomes a mechanical version-pin change. Validated end-to-end against
@nestjs/core@12.0.0-alpha.5locally (171/171 unit tests green, no config tweaks).NestJS 12 (targeted Q3 2026 per nestjs/nest#16391) ships all official packages as ESM with strict
exportsmaps and moves the default test runner from Jest to Vitest. Two changes here:bc042c6— source-level prep@nestjs/core/injector/*deep imports inpackages/core/lib/services/explorer.service.tswith the publicDiscoveryServiceAPI. Centralize the wrapper type asProviderWrapper(sourced fromDiscoveryService['getProviders']) and route the buses/event-map through it. No remaining deep imports anywhere in source or tests.--format cjs,esm --dts, condition-specificexportsmap with split.d.mts/.d.tsdeclarations.@nestjs/commonpeer to every integration package (only@nestjs/corewas declared).ef9bc91— Vitest migrationJest +
@swc/jestcan't load ESM-only@nestjs/*without convolutedtransformIgnorePatterns. Vitest understands ESM natively, which is where the NestJS toolchain is heading anyway.jest,@swc/jest,@types/jest,jest-mock. Addvitest@^4,@vitest/coverage-v8,unplugin-swc(handles decorator metadata).packages/config/vitest/base.mjs; per-packagevitest.config.mtsextends it. The.mjs/.mtssplit matters: Vite 7 is ESM-only and a TS base would need a Node-level TS loader — plain.mjssidesteps that.moduleNameMapperaliases to Viteresolve.alias(same regex shapes).jest.fn → vi.fn,jest.spyOn → vi.spyOn,jest.useFakeTimers/useRealTimers → vi.*,jest.Mocked<T> → Mocked<T>(withimport type { Mocked } from 'vitest').jest.fn()inpackages/testing/e2e/e2e-suite.tsfixed too."types": ["node", "vitest/globals"]in each package tsconfig sodescribe/it/expect/viresolve without per-file imports.test:cov:checkscript (shell-quoted JSON never worked); threshold enforcement (90/80/90) now lives in the shared vitest config.Consumer impact
Source-level changes are internal-only — the public
EventSourcingModule.forRoot{,Async}/forFeaturesurface, all decorators, and bus APIs are unchanged. The dual-publish change is purely additive: existing CJS consumers keep gettingdist/index.js; ESM consumers now get a nativedist/index.mjsinstead of CJS-via-interop.Strategy when v12 GA lands: drop v11, release as
@ocoda/event-sourcingv4.0.0.Test plan
pnpm build --filter="./packages/**"— 5/5 packages emit CJS + ESM + dual.d.ts/.d.mtspnpm --filter @ocoda/event-sourcing test— 171/171 tests pass on Vitest 4 (NestJS 11)pnpm --filter @ocoda/event-sourcing test:cov— 96.46% lines / 86.44% branches / 95.83% functionspnpm run ci --filter="./packages/**"— biome cleannode esm.mjs+node cjs.cjsagainstdist/index.{mjs,js}sed-applied peer/dev-dep bumps: install, build, 171/171 tests, coverage, lint all green — reverted before commit, but confirms zero remaining source-level issues for the GA bump🤖 Generated with Claude Code