upgrade to ESLint 9 flat config

upgrade dependencies
This commit is contained in:
vchikalkin 2024-11-26 13:18:14 +03:00
parent 74127dab53
commit b3615e6f55
20 changed files with 6540 additions and 4680 deletions

View File

@ -1,41 +1,48 @@
# @vchikalkin/eslint-config-awesome
# @vchikalkin/eslint-config-awesome 🎉
- 🛠️ Most rules autofixable
- 🎯 Designed to work with TypeScript, Nextjs, React projects
- 🎯 Designed to work with TypeScript, NextJS, React projects
- 🏆 Powered by [Canonical](https://github.com/gajus/eslint-config-canonical), [SonarJS](https://github.com/SonarSource/eslint-plugin-sonarjs)
- ⚙️ Using ESLint **Flat** config
## Requirements
- [ESLint 9](https://github.com/eslint/eslint)
- [TypeScript 5](https://www.typescriptlang.org/)
## 🚀 Usage
### 📥 Install
```bash
yarn add -D eslint @vchikalkin/eslint-config-awesome
pnpm add -D eslint typescript @vchikalkin/eslint-config-awesome
```
### ⚙️ Config `.eslintrc.js`
### ⚙️ Config `eslint.config.js`
For Next.js
Common usage:
```js
const { createConfig } = require('@vchikalkin/eslint-config-awesome');
const config = require('@vchikalkin/eslint-config-awesome');
module.exports = createConfig('next-typescript'); // or module.exports = createConfig('next');
module.exports = config['react-typescript'];
```
For React
Extend config:
```js
const { createConfig } = require('@vchikalkin/eslint-config-awesome');
const config = require('@vchikalkin/eslint-config-awesome');
module.exports = createConfig('react-typescript'); // or module.exports = createConfig('react');
```
For TypeScript
```js
const { createConfig } = require('@vchikalkin/eslint-config-awesome');
module.exports = createConfig('typescript');
module.exports = [
...config['react-typescript'],
{
rules: {
'rule-name': 'off',
},
ignores: ['node_modules'],
},
//...other configs
];
```
### Add script for package.json
@ -57,13 +64,14 @@ Install [VS Code ESLint extension](https://marketplace.visualstudio.com/items?it
```json
{
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.fixAll.eslint": "explicit",
"source.removeUnusedImports": "explicit"
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.fixAll.eslint": true,
"source.removeUnusedImports": true
},
"eslint.lintTask.enable": true,
"eslint.validate": [
"javascript",
"javascriptreact",
@ -71,7 +79,6 @@ Install [VS Code ESLint extension](https://marketplace.visualstudio.com/items?it
"typescript",
"typescriptreact",
"yaml"
],
"eslint.lintTask.enable": true
]
}
```

36
configs/react-typescript.js vendored Normal file
View File

@ -0,0 +1,36 @@
/* eslint-disable no-undef */
/* eslint-disable import/no-extraneous-dependencies */
const { fixupConfigRules } = require('@eslint/compat');
const { FlatCompat } = require('@eslint/eslintrc');
const auto = require('eslint-config-canonical/configurations/auto');
const sonarjs = require('eslint-plugin-sonarjs');
const rules = require('../rules');
const flatCompat = new FlatCompat();
/** @type {import('eslint').Linter.Config} */
module.exports = [
{ name: 'ESLint config awesome' },
...auto,
sonarjs.configs.recommended,
{
plugins: {
import: require('eslint-plugin-import'),
react: require('eslint-plugin-react'),
},
},
...fixupConfigRules(flatCompat.extends('plugin:@next/next/core-web-vitals')),
rules.common,
rules.react,
rules.sonar,
{
ignores: [
'**/node_modules',
'**/package-lock.json',
'**/pnpm-lock.yaml',
'**/package.json',
'**/tsconfig.json',
'**/eslint.config.js',
],
},
];

View File

@ -1,3 +1,3 @@
const createConfig = require('./utils/create-config');
const reactTypescript = require('./configs/react-typescript');
module.exports = { createConfig };
module.exports = { 'react-typescript': reactTypescript };

View File

@ -1,46 +0,0 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
globals: {
React: true,
JSX: true,
},
env: {
browser: true,
es2022: true,
node: true,
},
parser: '@typescript-eslint/parser',
extends: [
'canonical',
'plugin:sonarjs/recommended',
'canonical/next',
'prettier',
],
overrides: [
{
extends: ['canonical/typescript'],
files: '*.ts',
},
{
extends: ['canonical/react', 'canonical/typescript'],
files: '*.tsx',
},
{
extends: ['canonical/react'],
files: '*.jsx',
},
{
extends: ['canonical/graphql'],
files: ['*.graphql'],
},
// {
// files: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],
// extends: ['plugin:testing-library/react', 'canonical/jest'],
// },
],
plugins: [
'sonarjs',
'prettier',
// 'testing-library',
],
};

View File

@ -1,15 +0,0 @@
const javascript = require('../rules/javascript');
const typescript = require('../rules/typescript');
const sonar = require('../rules/sonar');
const react = require('../rules/react');
const next = require('../rules/next');
module.exports = {
rules: {
...javascript.rules,
...typescript.rules,
...sonar.rules,
...react.rules,
...next.rules,
},
};

View File

@ -1,37 +0,0 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
globals: {
React: true,
JSX: true,
},
env: {
browser: true,
es2022: true,
node: true,
},
extends: [
'canonical',
'plugin:sonarjs/recommended',
'canonical/next',
'prettier',
],
overrides: [
{
extends: ['canonical/react'],
files: '*.jsx',
},
{
extends: ['canonical/graphql'],
files: ['*.graphql'],
},
// {
// files: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],
// extends: ['plugin:testing-library/react', 'canonical/jest'],
// },
],
plugins: [
'sonarjs',
'prettier',
// 'testing-library',
],
};

View File

@ -1,13 +0,0 @@
const javascript = require('../rules/javascript');
const sonar = require('../rules/sonar');
const react = require('../rules/react');
const next = require('../rules/next');
module.exports = {
rules: {
...javascript.rules,
...sonar.rules,
...react.rules,
...next.rules,
},
};

View File

@ -1,18 +1,21 @@
{
"name": "@vchikalkin/eslint-config-awesome",
"version": "1.1.6",
"version": "2.0.0",
"license": "MIT",
"main": "index.js",
"dependencies": {
"@typescript-eslint/parser": "^6.19.0",
"eslint-config-canonical": "^42.3.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-canonical": "^4.15.1",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-sonarjs": "^0.22.0"
"@typescript-eslint/parser": "^8.16.0",
"eslint-config-canonical": "^44.3.31",
"eslint-plugin-sonarjs": "^2.0.4"
},
"devDependencies": {
"typescript": "^5.2.2"
"@eslint/compat": "^1.2.3",
"@eslint/eslintrc": "^3.2.0",
"@next/eslint-plugin-next": "^15.0.3",
"eslint": "^9.15.0",
"eslint-config-next": "^15.0.3",
"next": "^15.0.3",
"typescript": "^5"
},
"publishConfig": {
"access": "public"
@ -32,7 +35,6 @@
"zod"
],
"peerDependencies": {
"@babel/eslint-plugin": "^7.22.10",
"eslint": "^8.52.0"
"@next/eslint-plugin-next": "^15.0.3"
}
}

6422
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +0,0 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
globals: {
JSX: true,
},
env: {
browser: true,
es2022: true,
node: true,
},
parser: '@typescript-eslint/parser',
extends: ['canonical', 'plugin:sonarjs/recommended', 'prettier'],
overrides: [
{
extends: ['canonical/typescript'],
files: '*.ts',
},
{
extends: ['canonical/react', 'canonical/typescript'],
files: '*.tsx',
},
{
extends: ['canonical/react'],
files: '*.jsx',
},
],
plugins: ['sonarjs', 'prettier'],
};

View File

@ -1,13 +0,0 @@
const javascript = require('../rules/javascript');
const typescript = require('../rules/typescript');
const sonar = require('../rules/sonar');
const react = require('../rules/react');
module.exports = {
rules: {
...javascript.rules,
...typescript.rules,
...sonar.rules,
...react.rules,
},
};

20
rules/common.js Normal file
View File

@ -0,0 +1,20 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
name: 'Common rules override',
rules: {
'canonical/filename-match-exported': 'off',
'func-style': [
'warn',
'declaration',
{
allowArrowFunctions: true,
},
],
'import/no-unassigned-import': [
2,
{
allow: ['**/*.css'],
},
],
},
};

9
rules/index.js Normal file
View File

@ -0,0 +1,9 @@
const common = require('./common');
const sonar = require('./sonar');
const react = require('./react');
module.exports = {
common,
react,
sonar,
};

View File

@ -1,98 +0,0 @@
module.exports = {
rules: {
// Disabled
'brace-style': 'off',
'comma-dangle': 'off',
'comma-spacing': 'off',
'func-call-spacing': 'off',
indent: 'off',
'keyword-spacing': 'off',
'lines-between-class-members': 'off',
'no-extra-parens': 'off',
'object-curly-spacing': 'off',
'padding-line-between-statements': 'off',
quotes: 'off',
semi: 'off',
'space-before-blocks': 'off',
'space-before-function-paren': 'off',
'space-infix-ops': 'off',
// Config
'linebreak-style': ['error', 'windows'],
'import/extensions': 'off',
'newline-before-return': 'warn',
'function-paren-newline': 'off',
'promise/prefer-await-to-then': 'off',
'id-length': 'warn',
'import/no-unassigned-import': 'off',
'import/no-named-as-default-member': 'warn',
// Unicorn
'unicorn/no-array-for-each': 'off',
'unicorn/prevent-abbreviations': 'off',
'unicorn/prefer-node-protocol': 'off',
'unicorn/no-array-reduce': 'off',
'unicorn/prefer-module': 'off',
'unicorn/text-encoding-identifier-case': 'off',
'unicorn/filename-case': [
'error',
{
case: 'kebabCase',
ignore: ['^.*.(jsx|tsx)$'],
},
],
'unicorn/numeric-separators-style': [
'warn',
{
onlyIfContainsSeparator: false,
hexadecimal: {
minimumDigits: 0,
groupLength: 2,
},
binary: {
minimumDigits: 0,
groupLength: 4,
},
octal: {
minimumDigits: 0,
groupLength: 4,
},
number: {
minimumDigits: 5,
groupLength: 3,
},
},
],
// Canonical
'canonical/prefer-inline-type-import': 'off',
'@babel/object-curly-spacing': ['off'],
'canonical/filename-match-exported': ['off'],
'canonical/import-specifier-newline': ['off'],
'canonical/destructuring-property-newline': ['off'],
'canonical/export-specifier-newline': 'off',
'canonical/sort-keys': [
'warn',
'asc',
{
natural: true,
},
],
'canonical/id-match': ['off'],
'import/order': [
'error',
{
groups: [],
'newlines-between': 'always',
},
],
'func-style': ['warn', 'declaration', { allowArrowFunctions: true }],
'arrow-body-style': [
'error',
'as-needed',
{
requireReturnForObjectLiteral: false,
},
],
},
};

View File

@ -1,15 +0,0 @@
module.exports = {
rules: {
// Disabled
// Unicorn
// Canonical
// Ignore
'@next/next/link-passhref': 'off',
'@next/next/no-script-in-document': 'off',
'@next/next/no-script-in-head': 'off',
'@next/next/no-server-import-in-page': 'off',
},
};

4
rules/react.js vendored
View File

@ -1,7 +1,7 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
name: 'React rules override',
rules: {
'react/prop-types': 'off',
'react/jsx-sort-props': 'off',
'react/function-component-definition': [
'error',
{

View File

@ -1,6 +1,10 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
name: 'Sonar rules override',
rules: {
// Sonar
'sonarjs/no-duplicate-string': 'warn',
// fix
'sonarjs/no-empty-function': 'off',
'sonarjs/no-unused-expressions': 'off',
},
};

View File

@ -1,39 +0,0 @@
module.exports = {
rules: {
// Disabled
'@typescript-eslint/brace-style': 'off',
'@typescript-eslint/comma-dangle': 'off',
'@typescript-eslint/comma-spacing': 'off',
'@typescript-eslint/func-call-spacing': 'off',
'@typescript-eslint/indent': 'off',
'@typescript-eslint/keyword-spacing': 'off',
'@typescript-eslint/lines-between-class-members': 'off',
'@typescript-eslint/member-delimiter-style': 'off',
'@typescript-eslint/no-extra-parens': 'off',
'@typescript-eslint/object-curly-spacing': 'off',
'@typescript-eslint/padding-line-between-statements': 'off',
'@typescript-eslint/quotes': 'off',
'@typescript-eslint/semi': 'off',
'@typescript-eslint/space-before-blocks': 'off',
'@typescript-eslint/space-before-function-paren': 'off',
'@typescript-eslint/space-infix-ops': 'off',
'@typescript-eslint/type-annotation-spacing': 'off',
// Config
'@typescript-eslint/consistent-type-imports': 'error',
'@typescript-eslint/explicit-member-accessibility': [
'warn',
{
accessibility: 'explicit',
overrides: {
constructors: 'off',
},
},
],
'@typescript-eslint/naming-convention': 'warn',
// Unicorn
// Canonical
},
};

View File

@ -1,30 +0,0 @@
const { resolve } = require('node:path');
const project = resolve(process.cwd(), 'tsconfig.json');
/**
* @param {'next'|'next-typescript'|'react'|'react-typescript'|'typescript'} name
* @param {import('eslint').Linter.Config} overrideConfig
*/
function createConfig(name, overrideConfig) {
return {
extends: [
`@vchikalkin/eslint-config-awesome/${name}/config`,
`@vchikalkin/eslint-config-awesome/${name}/rules`,
],
parserOptions: {
project,
},
settings: {
'import/resolver': {
typescript: {
project,
},
},
},
ignorePatterns: ['node_modules/', 'dist/'],
...overrideConfig,
};
}
module.exports = createConfig;

4306
yarn.lock

File diff suppressed because it is too large Load Diff