// Jest (ESM + TypeScript via ts-jest). The codebase is NodeNext ESM with `.js` // import specifiers, so we strip the extension in moduleNameMapper to resolve // `./x.js` → `./x.ts` under jest. Run with NODE_OPTIONS=--experimental-vm-modules // (set in the package.json "test" script). /** @type {import('ts-jest').JestConfigWithTsJest} */ export default { testEnvironment: 'node', roots: ['/src'], testMatch: ['**/?(*.)+(spec).ts'], extensionsToTreatAsEsm: ['.ts'], moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1', }, transform: { '^.+\\.ts$': [ 'ts-jest', { useESM: true, tsconfig: { // Emit ESM regardless of package.json "type" (NodeNext would emit CJS // here and break under jest's ESM VM → "exports is not defined"). module: 'ESNext', moduleResolution: 'Bundler', isolatedModules: true, experimentalDecorators: true, emitDecoratorMetadata: true, verbatimModuleSyntax: false, }, }, ], }, }