Skip to content
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

[New] add support for Flat Config #3018

Merged
merged 1 commit into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
[New] add support for Flat Config
This change adds support for ESLint's new Flat config system.  It maintains backwards compatibility with `eslintrc`-style configs as well.

To achieve this, we're now dynamically creating flat configs on a new `flatConfigs` export.

Usage

```js
import importPlugin from 'eslint-plugin-import';
import js from '@eslint/js';
import tsParser from '@typescript-eslint/parser';

export default [
  js.configs.recommended,
  importPlugin.flatConfigs.recommended,
  importPlugin.flatConfigs.react,
  importPlugin.flatConfigs.typescript,
  {
    files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
    languageOptions: {
      parser: tsParser,
      ecmaVersion: 'latest',
      sourceType: 'module',
    },
    ignores: ['eslint.config.js'],
    rules: {
      'no-unused-vars': 'off',
      'import/no-dynamic-require': 'warn',
      'import/no-nodejs-modules': 'warn',
    },
  },
];
```
  • Loading branch information
michaelfaith authored and ljharb committed Jun 18, 2024
commit 806e3c2ccc65456a2d8532d575c9f443355bda82
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ insert_final_newline = true
indent_style = space
indent_size = 2
end_of_line = lf
quote_type = single
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ tests/files/with-syntax-error
tests/files/just-json-files/invalid.json
tests/files/typescript-d-ts/
resolvers/webpack/test/files
examples
# we want to ignore "tests/files" here, but unfortunately doing so would
# interfere with unit test and fail it for some reason.
# tests/files
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
- [`dynamic-import-chunkname`]: add `allowEmpty` option to allow empty leading comments ([#2942], thanks [@JiangWeixian])
- [`dynamic-import-chunkname`]: Allow empty chunk name when webpackMode: 'eager' is set; add suggestions to remove name in eager mode ([#3004], thanks [@amsardesai])
- [`no-unused-modules`]: Add `ignoreUnusedTypeExports` option ([#3011], thanks [@silverwind])
- add support for Flat Config ([#3018], thanks [@michaelfaith])

### Fixed
- [`no-extraneous-dependencies`]: allow wrong path ([#3012], thanks [@chabb])
Expand Down Expand Up @@ -1125,6 +1126,7 @@ for info on changes for earlier releases.

[#3036]: https://github.com/import-js/eslint-plugin-import/pull/3036
[#3033]: https://github.com/import-js/eslint-plugin-import/pull/3033
[#3018]: https://github.com/import-js/eslint-plugin-import/pull/3018
[#3012]: https://github.com/import-js/eslint-plugin-import/pull/3012
[#3011]: https://github.com/import-js/eslint-plugin-import/pull/3011
[#3004]: https://github.com/import-js/eslint-plugin-import/pull/3004
Expand Down Expand Up @@ -1874,6 +1876,7 @@ for info on changes for earlier releases.
[@meowtec]: https://github.com/meowtec
[@mgwalker]: https://github.com/mgwalker
[@mhmadhamster]: https://github.com/MhMadHamster
[@michaelfaith]: https://github.com/michaelfaith
[@MikeyBeLike]: https://github.com/MikeyBeLike
[@minervabot]: https://github.com/minervabot
[@mpint]: https://github.com/mpint
Expand Down
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ The maintainers of `eslint-plugin-import` and thousands of other packages are wo
npm install eslint-plugin-import --save-dev
```

### Config - Legacy (`.eslintrc`)

All rules are off by default. However, you may configure them manually
in your `.eslintrc.(yml|json|js)`, or extend one of the canned configs:

Expand All @@ -123,14 +125,41 @@ plugins:
- import

rules:
import/no-unresolved: [2, {commonjs: true, amd: true}]
import/no-unresolved: [2, { commonjs: true, amd: true }]
import/named: 2
import/namespace: 2
import/default: 2
import/export: 2
# etc...
```

### Config - Flat (`eslint.config.js`)

All rules are off by default. However, you may configure them manually
in your `eslint.config.(js|cjs|mjs)`, or extend one of the canned configs:

```js
import importPlugin from 'eslint-plugin-import';
import js from '@eslint/js';

export default [
js.configs.recommended,
importPlugin.flatConfigs.recommended,
{
files: ['**/*.{js,mjs,cjs}'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
rules: {
'no-unused-vars': 'off',
'import/no-dynamic-require': 'warn',
'import/no-nodejs-modules': 'warn',
},
},
];
```

## TypeScript

You may use the following snippet or assemble your own config using the granular settings described below it.
Expand Down
14 changes: 14 additions & 0 deletions config/flat/errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* unopinionated config. just the things that are necessarily runtime errors
* waiting to happen.
* @type {Object}
*/
module.exports = {
rules: {
'import/no-unresolved': 2,
'import/named': 2,
'import/namespace': 2,
'import/default': 2,
'import/export': 2,
},
};
19 changes: 19 additions & 0 deletions config/flat/react.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Adds `.jsx` as an extension, and enables JSX parsing.
*
* Even if _you_ aren't using JSX (or .jsx) directly, if your dependencies
* define jsnext:main and have JSX internally, you may run into problems
* if you don't enable these settings at the top level.
*/
module.exports = {
settings: {
'import/extensions': ['.js', '.jsx', '.mjs', '.cjs'],
},
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
};
26 changes: 26 additions & 0 deletions config/flat/recommended.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* The basics.
* @type {Object}
*/
module.exports = {
rules: {
// analysis/correctness
'import/no-unresolved': 'error',
'import/named': 'error',
'import/namespace': 'error',
'import/default': 'error',
'import/export': 'error',

// red flags (thus, warnings)
'import/no-named-as-default': 'warn',
'import/no-named-as-default-member': 'warn',
'import/no-duplicates': 'warn',
},

// need all these for parsing dependencies (even if _your_ code doesn't need
// all of them)
languageOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
};
11 changes: 11 additions & 0 deletions config/flat/warnings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* more opinionated config.
* @type {Object}
*/
module.exports = {
rules: {
'import/no-named-as-default': 1,
'import/no-named-as-default-member': 1,
'import/no-duplicates': 1,
},
};
2 changes: 0 additions & 2 deletions config/react.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@
* if you don't enable these settings at the top level.
*/
module.exports = {

settings: {
'import/extensions': ['.js', '.jsx'],
},

parserOptions: {
ecmaFeatures: { jsx: true },
},

};
2 changes: 1 addition & 1 deletion config/typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// `.ts`/`.tsx`/`.js`/`.jsx` implementation.
const typeScriptExtensions = ['.ts', '.cts', '.mts', '.tsx'];

const allExtensions = [...typeScriptExtensions, '.js', '.jsx'];
const allExtensions = [...typeScriptExtensions, '.js', '.jsx', '.mjs', '.cjs'];

module.exports = {
settings: {
Expand Down
25 changes: 25 additions & 0 deletions examples/flat/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import importPlugin from 'eslint-plugin-import';
import js from '@eslint/js';
import tsParser from '@typescript-eslint/parser';

export default [
js.configs.recommended,
importPlugin.flatConfigs.recommended,
importPlugin.flatConfigs.react,
importPlugin.flatConfigs.typescript,
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
languageOptions: {
parser: tsParser,
ecmaVersion: 'latest',
sourceType: 'module',
},
ignores: ['eslint.config.mjs', '**/exports-unused.ts'],
rules: {
'no-unused-vars': 'off',
'import/no-dynamic-require': 'warn',
'import/no-nodejs-modules': 'warn',
'import/no-unused-modules': ['warn', { unusedExports: true }],
},
},
];
17 changes: 17 additions & 0 deletions examples/flat/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "flat",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"lint": "cross-env ESLINT_USE_FLAT_CONFIG=true eslint src --report-unused-disable-directives"
},
"devDependencies": {
"@eslint/js": "^9.5.0",
"@types/node": "^20.14.5",
"@typescript-eslint/parser": "^7.13.1",
"cross-env": "^7.0.3",
"eslint": "^8.57.0",
"eslint-plugin-import": "file:../..",
"typescript": "^5.4.5"
}
}
12 changes: 12 additions & 0 deletions examples/flat/src/exports-unused.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type ScalarType = string | number;
export type ObjType = {
a: ScalarType;
b: ScalarType;
};

export const a = 13;
export const b = 18;

const defaultExport: ObjType = { a, b };

export default defaultExport;
12 changes: 12 additions & 0 deletions examples/flat/src/exports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type ScalarType = string | number;
export type ObjType = {
a: ScalarType;
b: ScalarType;
};

export const a = 13;
export const b = 18;

const defaultExport: ObjType = { a, b };

export default defaultExport;
7 changes: 7 additions & 0 deletions examples/flat/src/imports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//import c from './exports';
import { a, b } from './exports';
import type { ScalarType, ObjType } from './exports';

import path from 'path';
import fs from 'node:fs';
import console from 'console';
3 changes: 3 additions & 0 deletions examples/flat/src/jsx.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const Components = () => {
return <></>;
};
14 changes: 14 additions & 0 deletions examples/flat/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"jsx": "react-jsx",
"lib": ["ESNext"],
"target": "ESNext",
"module": "ESNext",
"rootDir": "./",
"moduleResolution": "Bundler",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
24 changes: 24 additions & 0 deletions examples/legacy/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module.exports = {
root: true,
env: { es2022: true },
extends: [
'eslint:recommended',
'plugin:import/recommended',
'plugin:import/react',
'plugin:import/typescript',
],
settings: {},
ignorePatterns: ['.eslintrc.cjs', '**/exports-unused.ts'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: ['import'],
rules: {
'no-unused-vars': 'off',
'import/no-dynamic-require': 'warn',
'import/no-nodejs-modules': 'warn',
'import/no-unused-modules': ['warn', { unusedExports: true }],
},
};
16 changes: 16 additions & 0 deletions examples/legacy/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "legacy",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"lint": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint src --ext js,jsx,ts,tsx --report-unused-disable-directives"
},
"devDependencies": {
"@types/node": "^20.14.5",
"@typescript-eslint/parser": "^7.13.1",
"cross-env": "^7.0.3",
"eslint": "^8.57.0",
"eslint-plugin-import": "file:../..",
"typescript": "^5.4.5"
}
}
12 changes: 12 additions & 0 deletions examples/legacy/src/exports-unused.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type ScalarType = string | number;
export type ObjType = {
a: ScalarType;
b: ScalarType;
};

export const a = 13;
export const b = 18;

const defaultExport: ObjType = { a, b };

export default defaultExport;
12 changes: 12 additions & 0 deletions examples/legacy/src/exports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type ScalarType = string | number;
export type ObjType = {
a: ScalarType;
b: ScalarType;
};

export const a = 13;
export const b = 18;

const defaultExport: ObjType = { a, b };

export default defaultExport;
7 changes: 7 additions & 0 deletions examples/legacy/src/imports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//import c from './exports';
import { a, b } from './exports';
import type { ScalarType, ObjType } from './exports';

import path from 'path';
import fs from 'node:fs';
import console from 'console';
3 changes: 3 additions & 0 deletions examples/legacy/src/jsx.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const Components = () => {
return <></>;
};
14 changes: 14 additions & 0 deletions examples/legacy/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"jsx": "react-jsx",
"lib": ["ESNext"],
"target": "ESNext",
"module": "ESNext",
"rootDir": "./",
"moduleResolution": "Bundler",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"test": "npm run tests-only",
"test-compiled": "npm run prepublish && BABEL_ENV=testCompiled mocha --compilers js:babel-register tests/src",
"test-all": "node --require babel-register ./scripts/testAll",
"test-examples": "npm run build && npm run test-example:legacy && npm run test-example:flat",
"test-example:legacy": "cd examples/legacy && npm install && npm run lint",
"test-example:flat": "cd examples/flat && npm install && npm run lint",
"prepublishOnly": "safe-publish-latest && npm run build",
"prepublish": "not-in-publish || npm run prepublishOnly",
"preupdate:eslint-docs": "npm run build",
Expand Down
Loading
Loading