AutoMapper not compatible with ESM module resolution
Is there an existing issue for this?
- [X] I have searched the existing issues
Describe the issue
I'm using ESM in my project with a TypeScript configuration like this:
{
"compilerOptions": {
"module": "Node16",
"moduleResolution": "Node16",
"target": "ES2022",
...
}
I've made my package use "type": "module" within package.json as well.
When trying to import anything from the @automapper packages, I get the following error:
/path/to/source/file.ts:2:10 - error TS2305: Module '"@automapper/classes"' has no exported member 'AutoMap'.
2 import { AutoMap } from '@automapper/classes';
Like-wise, if I try to import using require, I get:
/path/to/source/file.ts:2:10 - error TS1471: Module '@automapper/classes' cannot be imported using this construct. The specifier only resolves to an ES module, which cannot be imported with 'require'. Use an ECMAScript import instead.
2 import AutoMap = require('@automapper/classes');
Models/DTOs/VMs
No response
Mapping configuration
No response
Steps to reproduce
No response
Expected behavior
It should import from @automapper/* packages.
Screenshots
No response
Minimum reproduction code
See here: https://gist.github.com/gegenschall/f09683b9c0b80f0e00db68dea618432e
Package
- [ ] I don't know.
- [X]
@automapper/core - [X]
@automapper/classes - [X]
@automapper/nestjs - [X]
@automapper/pojos - [X]
@automapper/mikro - [X]
@automapper/sequelize - [ ] Other (see below)
Other package and its version
No response
AutoMapper version
8.7.6
Additional context
Node v18 TypeScript 4.8.4
I've added a minimal repro here.
I've run tsc --build --verbose --traceResolution in my project and I think TypeScript can't resolve the bundled .d.ts files, see this log excerpt:
======== Resolving module '@automapper/classes' from '/path/to/project/services/core-api/src/params/interfaces/param.interface.ts'. ========
Explicitly specified module resolution kind: 'Node16'.
'baseUrl' option is set to '/path/to/project', using this value to resolve non-relative module name '@automapper/classes'.
'paths' option is specified, looking for a pattern to match module name '@automapper/classes'.
'baseUrl' option is set to '/path/to/project', using this value to resolve non-relative module name '@automapper/classes'.
Resolving module name '@automapper/classes' relative to base url '/path/to/project' - '/path/to/project/@automapper/classes'.
Loading module as file / folder, candidate module location '/path/to/project/@automapper/classes', target file type 'TypeScript'.
File '/path/to/project/services/core-api/src/params/interfaces/package.json' does not exist according to earlier cached lookups.
File '/path/to/project/services/core-api/src/params/package.json' does not exist according to earlier cached lookups.
File '/path/to/project/services/core-api/src/package.json' does not exist according to earlier cached lookups.
File '/path/to/project/services/core-api/package.json' exists according to earlier cached lookups.
Loading module '@automapper/classes' from 'node_modules' folder, target file type 'TypeScript'.
Directory '/path/to/project/services/core-api/src/params/interfaces/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'automapper__classes'
Directory '/path/to/project/services/core-api/src/params/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'automapper__classes'
Directory '/path/to/project/services/core-api/src/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'automapper__classes'
Scoped package detected, looking in 'automapper__classes'
File '/path/to/project/services/core-api/node_modules/@types/automapper__classes.d.ts' does not exist.
Directory '/path/to/project/services/node_modules' does not exist, skipping all lookups in it.
Scoped package detected, looking in 'automapper__classes'
Found 'package.json' at '/path/to/project/node_modules/@automapper/classes/package.json'.
'package.json' does not have a 'typesVersions' field.
File '/path/to/project/node_modules/@automapper/classes/index.d.ts' exist - use it as a name resolution result.
Resolving real path for '/path/to/project/node_modules/@automapper/classes/index.d.ts', result '/path/to/project/node_modules/@automapper/classes/index.d.ts'.
======== Module name '@automapper/classes' was successfully resolved to '/path/to/project/node_modules/@automapper/classes/index.d.ts' with Package ID '@automapper/classes/[email protected]'. ========
File '/path/to/project/node_modules/@automapper/classes/package.json' exists according to earlier cached lookups.
======== Resolving module './lib/classes' from '/path/to/project/node_modules/@automapper/classes/index.d.ts'. ========
Explicitly specified module resolution kind: 'Node16'.
Loading module as file / folder, candidate module location '/path/to/project/node_modules/@automapper/classes/lib/classes', target file type 'TypeScript'.
Directory '/path/to/project/node_modules/@automapper/classes/lib/classes' does not exist, skipping all lookups in it.
Loading module as file / folder, candidate module location '/path/to/project/node_modules/@automapper/classes/lib/classes', target file type 'JavaScript'.
Directory '/path/to/project/node_modules/@automapper/classes/lib/classes' does not exist, skipping all lookups in it.
======== Module name './lib/classes' was not resolved. ========
I would think that this is the culprit?
Thanks for the reproduce. I'll take a look asap
@gegenschall @nartc
I'm not sure if it's something with this package or with the settings you have. But for some reason the combination of module: "Node16" and moduleResolution: "Node16".
For me this works:
{
"compilerOptions": {
"module": "ES2022",
"moduleResolution": "node",
"allowJs": true,
"maxNodeModuleJsDepth": 10,
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "ES2022",
"sourceMap": true,
"esModuleInterop": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
"types": ["reflect-metadata", "jest"],
"typeRoots": ["./types", "./node_modules/@types"]
},
"ts-node": {
"esm": true,
"experimentalSpecifierResolution": "node"
},
"include": ["src/**/*", "test/**/*"]
}