New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resolution relative to cwd/__placeholder__.js
is flaky, breaks when deps nested below top level
#13764
Comments
Note: another (imo, perfectly reasonable) way to approach this would be to say that Then, if the eslint bin is not the |
Oh! Or, maybe, the resolution should be relative to the When I hard-code the full file paths to the extended config files, it runs into the same issue with the Attempting to shove in an absolute file path there results in:
|
Thanks @isaacs for the incredibly thorough deep dive! @nzakas is working on a simplification of our config system that will solve this, assuming I understand the issue correctly. In summary, configs and plugins will Originally, all ESLint configs were JSON-serializable and we didn't have JS configs, so as we added support for plugins and shareable configs, we ended up with complex loading and merging strategies inside of ESLint rather than relying on |
Thanks @isaacs and @btmills for all of the details. Indeed, we are in a period where the current config system is frozen and won't be making any more changes to it to ensure we'll have some level of backwards compatibility when the new config system is ready. This is exactly the type of problem we are looking to avoid with the new config system, so the good news is that a solution is coming and it won't be nearly as ugly as if we had to fix the original config system. |
Oh, Hey, @nzakas, there's a name I haven't seen in a while, hope you're doing well :) Sounds good. In the meantime, I've just suggested yargs use |
@isaacs indeed, it has been a minute! I’m hanging in, I hope you’re doing well, too. |
Closing as we are working on the new config system. |
Tell us about your environment
What parser (default,
@babel/eslint-parser
,@typescript-eslint/parser
, etc.) are you using?Not sure. This is in the
yargs
project, which usesstandard
, viastandardx
.Please show your full configuration:
Configuration
The config used directly in yargs with eslint 7.x is this:
The one used by standard, at
node_modules/standard/eslint.json
isWhat did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.
As of npm v7,
peerDependencies
are installed by default, and npm makes every effort (short of venturing into NP-hard territory) to ensure that every dependency's peerDependencies will be met according to their stated constraints. This can involve nesting dependencies in a peerDependency set deeper in the tree.The
--legacy-peer-deps
flag allows npm 7 to ignore all peerDependencies, as npm versions 4-6 did.When installing the yargs project using npm v7.0.2, the install works properly, and
npm ls --all
does not report any conflicting peer dependencies. Hooray!npm ls output when installed with default settings in npm v7.0.2
Hooray! no problems found! Every package has its peerDependencies constraints honored.
By comparison, when installed with the
--legacy-peer-deps
flag, we get this resultingnpm ls
output:npm ls output when installed with legacy peer deps mode
Note that
eslint@7.11.0
is being provided as a resolution foreslint-plugin-react
andeslint-plugin-import
, despite those packages having apeerDependencies
constraint requiring eslint 6.x.where this gets interesting...
Yargs has dependencies on both
gts
(which uses eslint 7) andstandardx
(which uses eslint 6). In order to satisfy the dependency constraints, standard needs to have a nested copy ofeslint
innode_modules/standard/node_modules/eslint
. This is not new. What is new is that all the dependencies of standard which havepeerDependencies
oneslint
are now also nested undernode_modules/standard/node_modules/...
, so that they will get the version of eslint that they claim to work with.Standard then loads eslint with a config (referenced above) that includes
"extends": ["standard", "standard-jsx"]
. Eslint looks for a package namedeslint-config-standard
, but does so by attempting to resolve it relative tocwd + '/__placeholder__.js'
.Since
eslint-config-standard
has been nested undernode_modules/standard/node_modules/...
, however, it cannot be found relative to the root project directory.The interesting thing is that it actually does work (albeit, likely somewhat by accident) when the peerDependencies on eslint 6 are not honored, likely because the config shape just hasn't changed too much between 6 and 7. Of course, in general, for a package manager, this is not even slightly safe to assume, so we don't assume it any more in npm 😅.
A better approach, when loading from an implicit package name without any explicit file path, might be for eslint to attempt to load the module by doing
require.resolve()
(to get it relative to the eslint package itself), or relative to the module that firstrequire()
'd eslint (ifrequire.main
is not eslint), and only then fromprocess.cwd()
.This does all work fine, of course, if eslint is loaded as a bin script rather than a library used by some other bin script, as gts, standard, standardx, and many others do.
What did you expect to happen?
Expect
eslint
to find theeslint-config-standard
module in the package tree, as it is visible to eslint and the code calling eslint, even though it is not visible to arequire()
from thecwd
.What actually happened? Please include the actual, raw output from ESLint.
Are you willing to submit a pull request to fix this bug?
Sure, but I probably won't get to it as quickly as someone more familiar with the project.
The text was updated successfully, but these errors were encountered: