Closed adamchainz closed 3 days ago
As the issue template says, we can't investigate any bug reports without a repro case. If you can please create a StackBlitz showing this behavior we can take a look.
Link: https://stackblitz.com/edit/stackblitz-starters-jycfg3?file=eslint.config.js
Screenshot of repro on stackblitz:
Ah okay, I see what's happening.
Yes, you still need to install @eslint/js
into your project manually (as you would any other import that you have in a config file). Even though @eslint/js
is a dependency of ESLint, that doesn't mean you can use it directly without installing it first.
@nzakas, I have hit this issue as well when trying to use eslint
with https://pre-commit.ci/. The issue here is that pre-commit.ci installs eslint
"globally" and won't run npm install
. The plugin takes a list of extra dependencies and installs them into npm's virtual environment. If eslint used this global node_modules
folder all would work, but eslint
fails to find any dependencies in the local folder on pre-commit.ci because npm install
was never run.
Is there some way to tell eslint
to look for dependencies elsewhere? I know that in normal use you don't want to support this, but I think for a CI environment being able to somehow add another source of node_modules
is essential.
It seems that eslint used to take a --resolve-plugins-relative-to
flag, but no longer does; is there some way to get behavior like this back, even if's hacky?
Thank you!
@nzakas I tried this again and confirmed that NODE_PATH
is set correctly. I created a reproduction here with details:
https://github.com/sritchie/eslint-repro
Here are the details, also in the repro README. (The implicit question here is, is this
eslint.config.mjs
?In the repro, .pre-commit-config.yaml
looks like this:
repos:
- repo: local
hooks:
- id: eslint
name: eslint
language: node
additional_dependencies:
- eslint@9.3.0
- globals@15.3.0
entry: ./run_eslint.sh
This will install a node environment with the listed "additional dependencies"
(installed via npm install
), and then trigger the entry
point.
I used a shell script here, run_eslint.sh
, so I could show that the
environment variables are set correctly, and that the NODE_PATH
does indeed
have eslint
and globals
installed into it.
However, when I either run the script explicitly:
./run_eslint.sh
Or run it through pre-commit
:
pre-commit run eslint --all
I see the following output:
NODE_PATH:
/Users/sritchie/.cache/pre-commit/repoxz3rawvg/node_env-default/lib/node_modules
NPM_CONFIG_PREFIX:
/Users/sritchie/.cache/pre-commit/repoxz3rawvg/node_env-default
contents of NODE_PATH:
corepack eslint globals npm pre_commit_placeholder_package
Oops! Something went wrong! :(
ESLint: 9.3.0
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'globals' imported from /Users/sritchie/code/mit/eslint-repro/eslint.config.mjs
Did you mean to import "globals/index.js"?
at packageResolve (node:internal/modules/esm/resolve:841:9)
at moduleResolve (node:internal/modules/esm/resolve:914:18)
at defaultResolve (node:internal/modules/esm/resolve:1119:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:542:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:511:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:241:38)
at ModuleJob._link (node:internal/modules/esm/module_job:126:49)
telling me that NODE_PATH
is set to a directory containing globals
, but
eslint
can't find the import in eslint.config.mjs
.
I would have expected that this eslint.config.mjs
should work fine, given that
globals
is installed:
import globals from "globals";
export default [
{
languageOptions: { globals: globals.browser },
files: ["src/**/*.js"],
},
];
Environment
Node version: v20.12.0 npm version: 10.8.0 Local ESLint version: v9.2.0 Global ESLint version: n/a Operating System: macOS
What parser are you using?
Default (Espree)
What did you do?
An empty directory with just this
eslint.config.js
:Run the CLI with npx as documented:
What did you expect to happen?
The
require
/import
statements resolve.@eslint/js
is installed with ESLint: https://github.com/eslint/eslint/blob/06f1d1cd874dfc40a6651b08d766f6522a67b3f0/package.json#L72 .What actually happened?
Crash:
The way ESLint loads the config file means that its import statements aren’t resolved.
(The bug also occurs with ESM config in
eslint.config.mjs
, with a slightly different error message:Cannot find package '@eslint/js' imported from /Users/chainz/tmp/test-eslint/eslint.config.mjs
.)Link to Minimal Reproducible Example
Open https://stackblitz.com/edit/stackblitz-starters-jycfg3?file=eslint.config.js and run
npx eslint
:Participation
Additional comments
It seems that to use flat config, you must install ESLint in the same directory as configuration? If so, that really breaks using tool managers—I found this out when using ESLint under pre-commit, which manages tools in its own directory outside of your project.