import-js / eslint-plugin-import

ESLint plugin with rules that help validate proper imports.
MIT License
5.46k stars 1.56k forks source link

Bug: Cannot find module @typescript-eslint/parser with @typescript-eslint/parser 6.4.0 and npm workspaces #2862

Open vhiairrassary opened 1 year ago

vhiairrassary commented 1 year ago

After upgrading @typescript-eslint/eslint-plugin and @typescript-eslint/parser from 5.60.0 to 6.4.0, I am unable to use eslint-plugin-import anymore due to a hoisting issue (I am using the workspaces feature with npm 9.8.0). This upgrade is the only change.

The error is:

/my-repo/js/packages/pkg-1/src/lib/helpers/my-helper.ts
  1:37  error  Parse errors in imported module 'react': Cannot find module '@typescript-eslint/parser'
Require stack:
- /my-repo/js/node_modules/eslint-module-utils/module-require.js
- /my-repo/js/node_modules/eslint-module-utils/parse.js
- /my-repo/js/node_modules/eslint-plugin-import/lib/ExportMap.js
- /my-repo/js/node_modules/eslint-plugin-import/lib/rules/named.js
- /my-repo/js/node_modules/eslint-plugin-import/lib/index.js
- /my-repo/js/node_modules/@eslint/eslintrc/dist/eslintrc.cjs (undefined:undefined)  import/namespace

I am pretty sure it is a similar to what is described at https://github.com/npm/cli/issues/5840. Here are the directory structures:

As you can see @typescript-eslint/parser at version 6.4.0 is no longer hoisted in the root node_modules directory, which is preventing eslint-plugin-import from requiring it. From my understanding, the correct way to fix it would be do declare @typescript-eslint/parser as an optional peer dependency of eslint-plugin-import, with something like (as explained here: https://github.com/npm/cli/issues/5840#issuecomment-1310983504):

"peerDependencies": { 
  "@typescript-eslint/parser": "*"
},
"peerDependenciesMeta": {
  "@typescript-eslint/parser": {
    "optional": true
  }
}

Does this bug report sound valid to you?

ljharb commented 1 year ago

Somewhat - the closing comment you linked to says

This is a bug with a package requiring a dependency not declared in its own package.json.

but that's not actually a bug - it's a thing that this plugin, and other packages, occasionally rely on to function properly, that's always worked.

In other words, the real problem is that the workspaces feature (not just npm's; all of them) incorrectly rely on hoisting modules to share dependencies, and this just isn't intrinsically compatible with the way people need monorepos to interact with node's module algorithm.

Adding a peer dep, even an optional one, is a breaking change, so that's not a change I'm going to make.

connorjs commented 1 year ago

I also hit this error while upgrading typescript eslint. In my monorepo, I (also) installed @typescript-eslint/parser at the root to force the hoisting and (I think) that fixed it.

Just wanted to share a possible workaround for others that find their way here.

npm i -D @typescript-eslint/parser # at the root
vhiairrassary commented 1 year ago

Thank you @connorjs that sounds like a great workaround!

prisis commented 11 months ago

Or you install "@rushstack/eslint-patch" and put this line on top of your eslint config require("@rushstack/eslint-patch/modern-module-resolution");