mapper icon indicating copy to clipboard operation
mapper copied to clipboard

AutoMapper not compatible with ESM module resolution

Open gegenschall opened this issue 3 years ago • 3 comments

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

gegenschall avatar Oct 18 '22 08:10 gegenschall

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?

gegenschall avatar Oct 21 '22 06:10 gegenschall

Thanks for the reproduce. I'll take a look asap

nartc avatar Oct 24 '22 16:10 nartc

@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/**/*"]
}

toonvanstrijp avatar Mar 08 '23 21:03 toonvanstrijp