Support eslint flat config
Likely depends on https://github.com/import-js/eslint-plugin-import/issues/2556 but it's good to track nonetheless.
Ref: https://github.com/eslint/eslint/issues/18093
eslint-plugin-i is now eslint-plugin-import-x.
I'm focusing on TypeScript migration first, see also #41.
After that, I'll start working on new features like supporting flat config.
Just to mention, some rules will break when using flat config. See this comment
In brief, eslint will fail to use eslint.config.js as config file after enabling import/no-unused-modules with unusedExports: true
Related issues:
- https://github.com/eslint/eslint/issues/16485
- https://github.com/import-js/eslint-plugin-import/issues/2907
- https://github.com/import-js/eslint-plugin-import/issues/2964
Interesting, we are using eslint-plugin-import-x now with the Flat Config:
- https://github.com/import-js/eslint-plugin-import/issues/2948#issuecomment-2119214365
This seems to be working for us so far:
Simplified version of the code:
import eslintImportX from 'eslint-plugin-import-x';
/** @type {import('@typescript-eslint/utils/ts-eslint').FlatConfig.ConfigArray} */
const configArray = [
{
plugins: {
'import-x': eslintImportX,
},
settings: {
'import-x/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import-x/resolver': {
// Load <rootdir>/tsconfig.json
typescript: true,
node: true,
},
},
rules: {
// Error on imports that don't match the underlying file system
// https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-unresolved.md
'import-x/no-unresolved': 'error',
},
];
@karlhorky I am trying out this plugin with the flat config. I copy pasted the config from your post, but I get these errors:
(I enabled more rules than simply import-x/no-unresolved.)
Any idea on how to fix?
module.exports = {
extends: [
'plugin:import-x/recommended',
'plugin:import-x/typescript',
],
}
can only be translate into
export default [
...compat.config(pluginImportX.configs.recommended), // https://github.com/un-ts/eslint-plugin-import-x/issues/29#issuecomment-2148843214
pluginImportX.configs.typescript, // no need of wrapping in compat.config() since there's no pluginImportX.configs.typescript.plugins
];
since https://github.com/un-ts/eslint-plugin-import-x/blob/3abe5e49683e0f973232bb631814b935e1ca7091/src/config/recommended.ts#L7 is still passing string as plugin.
@n0099 where is compat coming from?
Is there an example of a simple flat config for eslint v9 that uses this plugin?
My super simple set up works for everything but the import sorting.
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginImportX from "eslint-plugin-import-x";
export default [
{
languageOptions: { globals: globals.browser },
ignores: ["./dist/"],
},
pluginJs.configs.recommended,
...tseslint.configs.recommended,
pluginImportX.configs.typescript,
];
@n0099 where is
compatcoming from?
@eslint/eslintrc https://github.com/ota-meshi/typescript-eslint-parser-for-extra-files/issues/95#issuecomment-2148604881
import { FlatCompat } from '@eslint/eslintrc';
My super simple set up works for everything but the import sorting.
If you only want to extends from typescript rules, the plugin is not defined in the rule: https://github.com/un-ts/eslint-plugin-import-x/blob/3abe5e49683e0f973232bb631814b935e1ca7091/src/config/typescript.ts#L16-L35
so manually add plugin define to let eslint know where to find define for rules with prefix import-x/
+ { plugins: { 'import-x': pluginImportX } },
pluginImportX.configs.typescript,
or just also extending recommended rules:
+ ...compat.config(pluginImportX.configs.recommended),
pluginImportX.configs.typescript,
Where do you import compat from?
Where do you import compat from?
https://github.com/un-ts/eslint-plugin-import-x/issues/29#issuecomment-2156223337
Just to mention, some rules will break when using flat config. See this comment
In brief, eslint will fail to use
eslint.config.jsas config file after enablingimport/no-unused-moduleswithunusedExports: trueRelated issues:
* [Bug: can not find flat file config eslint/eslint#16485](https://github.com/eslint/eslint/issues/16485) * [import/no-unused-modules breaks `--no-eslintrc` and eslint fails import-js/eslint-plugin-import#2907](https://github.com/import-js/eslint-plugin-import/issues/2907) * [Add note(s) to docs about flat configs and/or no-unused-modules' `unusedExports` not being supported in flat configs import-js/eslint-plugin-import#2964](https://github.com/import-js/eslint-plugin-import/issues/2964)
Also this https://github.com/eslint/eslint/issues/18087
Chiming in here to say that I don't think the ecosystem uses import/no-unused-modles anymore in favor of knip. Since ESLint is designed to parse individual files (as the linked GitHub issue above shows), it makes more sense to do this kind of project-level checking in a separate tool.
Are any other rules than import/no-unused-modles broken by the flat config?
Let's deprecate no-unused-modles then~!
@Zamiell The discussion about deprecating no-unused-modules rule can be found here: https://github.com/un-ts/eslint-plugin-import-x/issues/90
Never heard about knip, but I'm generally in favor of at least disabling rules that are duplicate with what typescript already validates, if the linted file is typescript, of course. But I guess this is more of a config topic than a plugin topic.
It works great in flat config 👍🏻 but no-unused-modules leads to an eslint error that the eslint config is missing.
It works great in flat config 👍🏻 but
no-unused-modulesleads to an eslint error that the eslint config is missing.
Yes. This is because no-unused-modules uses an ESLint internal private API that was designed to be used for crawling eslintrc files.
Currently, I am working on a more performant no-cycle rule alternative.
@silverwind would you like to replace the FileEnumerator w/ a globbing function?
In https://github.com/import-js/eslint-plugin-import/pull/3018 they used @nodelib/fs.walk to replace it, if I understand correctly. Seems like a popular enough dependency to use.
Maybe @michaelfaith would be interested in porting their work here in case that PR stalls because of those "node 4 concerns" which we do not have with this fork 😆.
Maybe @michaelfaith would be interested in porting their work here in case that PR stalls because of those "node 4 concerns" which we do not have with this fork 😆.
Yeah. @michaelfaith if you are interested, you can port that PR to eslint-plugin-import-x as well. We use TypeScript and we are not limited to Node.js 4.
Sure, I don't mind helping out, when I have some time.
In https://github.com/import-js/eslint-plugin-import/pull/3018 they used
@nodelib/fs.walkto replace it
note the fs.walk approach discussed in https://github.com/import-js/eslint-plugin-import/pull/3018 for replacing FileEnumerator depends on a proposed eslint API that’s currently only hypothetical'
I’d support deprecating no-unused-modules and skipping support for using that rule with flat config
that’s currently only hypothetical
Did you mean context.session?
I’d support deprecating
no-unused-modulesand skipping support for using that rule with flat config
I've considered deprecating no-unused-modules (https://github.com/un-ts/eslint-plugin-import-x/issues/90) but I changed my idea.
And as long as we don't include this rule in the flat config, everything would be fine.
I'd definitely keep it at this point, it's too valuable and not everyone wants to install another dependency and fight its config just to replace one rule.
Yeah
that’s currently only hypothetical
Did you mean
context.session?
Yeah, I wouldn't really say "hypothetical". Proposed is accurate though. The two functions that I used in that implementation were added in a POC branch of the eslint repo to prove the proposed api. The idea is that the code would use those functions if they were on the context, and if not, fall back to the old implementation. And if, between now and when the API is finalized, those functions get introduced with a slightly different shape, then the implementation would need to be adjusted. It'd be the same here, if that's the route you want to go. I did use the POC branch in the eslint repo to work against, though. So it did prove the solution out.
Oh, and to add a little more context: that api very likely would have already been added to ESLint in v9, if it weren't for the feet-dragging from the eslint-plugin-import project in validating the approach. If the API is ever going to be added, there needs to be an expressed demand for it. So if you want it, this could be a good way to express that demand. Food for thought.
I started a draft PR, with everything except the changes to no-unused-module. I wanted to confirm that that's the direction you want to go before implementing it.
that’s currently only hypothetical
Did you mean context.session?
Yes, I’m talking about context.session.isDirectoryIgnored() and context.session.isFileIgnored()! These were proposed by nzakas as a way to enable fs.walk approaches to replicate the functionality of the FileEnumerator API. There’s a POC in a branch of eslint, but hasn’t been merged into eslint proper, as @michaelfaith explained!