ESLintのFlat Configにマイグレーションしたメモ

## 概要
[前回](https://qiita.com/hibohiboo/items/73899ea187f76479af8d)はESLintの暫定対応を行った。
[v8 -> v9 マイグレーションガイド](https://eslint.org/docs/latest/use/configure/migration-guide)では難しそうに感じたが、[ESLintのFlat Config移行でやって良かったこと](https://zenn.dev/mkizka/articles/7ff4f256e38401)で紹介されている[typescript-eslint](https://typescript-eslint.io/getting-started)に従えばスムーズに進められそうだったので[monorepoの設定](https://qiita.com/hibohiboo/items/eadbef66932029a28bab)を行ったリポジトリで対応した。

[ソースコード](https://github.com/hibohiboo/kartagraph-monorepo/tree/90bbf0ed1c66985aff263985112323e8fa0bbf27)

[対応コミット](https://github.com/hibohiboo/kartagraph-monorepo/commit/84ab3122ce2232a401e9f2b09288d4645e6115e8)

## 大きな変更点
[typescript-eslint](https://typescript-eslint.io/)を導入し、`@typescript-eslint/eslint-plugin`は廃止した。
```diff:package.json
{
  "name": "@kartagraph/eslint-config-custom",
+  "type": "module",
  "private": true,
  "license": "MIT",
  "version": "0.0.0",
  "devDependencies": {
+    "@eslint/eslintrc": "^3.0.2",
+    "@eslint/js": "^9.0.0",
-    "@typescript-eslint/eslint-plugin": "^7.6.0",
-    "@typescript-eslint/parser": "^7.6.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-config-turbo": "^1.13.2",
    "eslint-plugin-import": "^2.29.1",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.6",
    "eslint-plugin-unused-imports": "^3.1.0",
+    "typescript": "^5.4.5",
+    "typescript-eslint": "^7.6.0"
  },
  "scripts": {
+    "inspect": "npx @eslint/config-inspector",
    "ncu": "ncu -u"
  }
}
```

jsファイルは、大きく書き換えた。

```diff:package/eslint-config-custom/defaults.js
+ import js from '@eslint/js';
+ import tseslint from 'typescript-eslint';
+ import importPlugin from 'eslint-plugin-import';
+ import unuserdPlugin from 'eslint-plugin-unused-imports';

- module.exports = {
+ export default tseslint.config({

-  "extends": ["eslint:recommended","plugin:@typescript-eslint/recommended"],
+  extends: [js.configs.recommended, ...tseslint.configs.recommended],

- "plugins": ["import", "unused-imports"],
+  plugins: { import: importPlugin, 'unused-imports': unuserdPlugin },

  "rules": {
    "semi": ["error", "always"],
    "unused-imports/no-unused-imports": "warn", 
    "import/order": ["warn", { "groups": ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"] // importの並び順の設定
                             , "pathGroupsExcludedImportTypes": ["builtin"]
                             , "pathGroups": [{ "pattern": "@src/**", "group": "parent", "position": "before"}] // エイリアスの位置を指定
                             , "alphabetize": { "order": "asc"} // グループ内のソート順
                             }
                    ]
  },
});
```


## そのままではエラーが出るプラグインを移行する


エラーメッセージの例
```
Oops! Something went wrong! :(
ESLint: 9.0.0
A config object has a "plugins" key defined as an array of strings.
```
```
Oops! Something went wrong! :(
ESLint: 9.0.0
A config object is using the "extends" key, which is not supported in flat config system.
```

[Using eslintrc Configs in Flat Config](https://eslint.org/docs/latest/use/configure/migration-guide#using-eslintrc-configs-in-flat-config)に書かれている`FlatCompat`を使用する。


```diff
import tseslint from 'typescript-eslint';
- import turboConfig from 'eslint-config-turbo';
+ import { FlatCompat } from "@eslint/eslintrc";
+ import path from "path";
+ import { fileURLToPath } from "url";

+ const __filename = fileURLToPath(import.meta.url);
+ const __dirname = path.dirname(__filename);

+ const compat = new FlatCompat({
+     baseDirectory: __dirname
+ });

export default tseslint.config({
   extends: [
     ...customConfig,
-    turboConfig,
+    ...compat.extends('eslint-config-turbo')
     prettierConfig
  ],
```

## eslint-config-inspector

[config-inspector](https://github.com/eslint/config-inspector)の出力をGithubActionsに組みたいが、[v0.4.5](https://github.com/eslint/config-inspector/releases/tag/v0.4.5)では[Issueが出ている](https://github.com/eslint/config-inspector/issues/33)のでまだ難しそう。
これが解決したら出力できるようにしたい。

### 2024.04.25 追記 v0.4.7で出力できるようになった。

[出力結果](https://hibohiboo.github.io/kartagraph-monorepo/public/eslint-config-inspector/)

[Github Actions yaml](https://github.com/hibohiboo/kartagraph-monorepo/blob/cccea868540f1f1ebdc745acb547923be283c28d/.github/workflows/pages.yml)
[buildスクリプト package.json](https://github.com/hibohiboo/kartagraph-monorepo/blob/cccea868540f1f1ebdc745acb547923be283c28d/packages/eslint-config-custom/package.json)

## （2024.04.22 追記） ESLint 9.1.0 にアップデートしたらエラーとなったメモ
### 現象
下記のエラーが出るようになった。

```
Oops! Something went wrong! :(

ESLint: 9.1.0

Error: 'patterns' must be a non-empty string or an array of non-empty strings
```

### 原因

[前回](https://qiita.com/hibohiboo/items/73899ea187f76479af8d)、`ESLINT_USE_FLAT_CONFIG=false`にしていたものを戻していなかった。

### 対応
`ESLINT_USE_FLAT_CONFIG=true`に変更する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/2fe24cbb-293e-8c5b-daee-f856a6af0dfc.png)

### 新たなエラー

```
ESLint: 9.1.0

Error: This method cannot be used with flat config. Add your entries directly into the config array.
    at assertEslintrcConfig (\node_modules\eslint\lib\linter\linter.js:1256:15)  
    at Linter.getRules (\node_modules\eslint\lib\linter\linter.js:2185:9)        
    at Object.<anonymous> (\node_modules\eslint-plugin-unused-imports\lib\rules\load-rule.js:10:32)
    at Module._compile (node:internal/modules/cjs/loader:1369:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1427:10)
    at Module.load (node:internal/modules/cjs/loader:1206:32)
    at Module._load (node:internal/modules/cjs/loader:1022:12)
    at Module.require (node:internal/modules/cjs/loader:1231:19)
    at require (node:internal/modules/helpers:179:18)
o-unused-vars.js:11:14)
```

### 暫定対応
'eslint-plugin-unused-imports'をコメントアウトした。
しばらくこのプラグインが使えなくなるが、lintがまったく効かないよりましだと判断。
9.0.0に戻すこともあまりやりたくないので。

[Issue](https://github.com/sweepline/eslint-plugin-unused-imports/issues/75)は出ているので、待つこととしたい。 → 待ったら直った

```packges/eslint-config-custom/default.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import importPlugin from 'eslint-plugin-import';
// import unuserdPlugin from 'eslint-plugin-unused-imports';

export default tseslint.config({
  extends: [js.configs.recommended, ...tseslint.configs.recommended],
  plugins: { import: importPlugin, 
    // 'unused-imports': unuserdPlugin
  },
  rules: {
    semi: ['error', 'always'],
    // 'unused-imports/no-unused-imports': 'warn',
    'import/order': [
      'warn',
      {
        groups: [ 'builtin','external','internal','parent','sibling','index','object','type' ], // importの並び順の設定
        pathGroupsExcludedImportTypes: ['builtin'],
        pathGroups: [ { pattern: '@src/**', group: 'parent', position: 'before' } ], // エイリアスの位置を指定
        alphabetize: { order: 'asc' }, // グループ内のソート順
      },
    ],
  },
});
```

## moduleでないプロジェクトでの設定
下記のエラーがでるような場合。
```
SyntaxError: Cannot use import statement outside a module
```

`eslint.config.js` -> `eslint.config.mjs`に変更。

## eslint 9.2.0に上げた時のメモ 2024.05.05 追記

`eslint-plugin-unused-imports`が使えるようになっていた。
[この時点のソースコード](https://github.com/hibohiboo/kartagraph-monorepo/tree/fd2f5f8448628b0dfbc46df55529607ebe0eba0c)

<details><summary>eslintの依存性エラーが出て試行錯誤したメモ。結局--legacy-peer-depsで解決</summary><div>

下記のエラーがでた。

```
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@9.0.0
npm WARN node_modules/eslint
npm WARN   dev eslint@"^9.2.0" from the root project
npm WARN   5 more (@eslint-community/eslint-utils, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" from eslint-plugin-import@2.29.1
npm WARN node_modules/eslint-plugin-import
npm WARN   dev eslint-plugin-import@"^2.29.1" from @kartagraph/eslint-config-custom@0.0.0
npm WARN   packages/eslint-config-custom
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: @typescript-eslint/eslint-plugin@7.4.0
npm WARN Found: eslint@9.2.0
npm WARN node_modules/eslint
npm WARN   dev eslint@"^9.2.0" from the root project
npm WARN   5 more (@eslint-community/eslint-utils, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^8.56.0" from @typescript-eslint/eslint-plugin@7.4.0
npm WARN node_modules/@typescript-eslint/eslint-plugin
npm WARN   peerOptional @typescript-eslint/eslint-plugin@"6 - 7" from eslint-plugin-unused-imports@3.1.0
npm WARN   node_modules/eslint-plugin-unused-imports
npm WARN
npm WARN Conflicting peer dependency: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^8.56.0" from @typescript-eslint/eslint-plugin@7.4.0
npm WARN   node_modules/@typescript-eslint/eslint-plugin
npm WARN     peerOptional @typescript-eslint/eslint-plugin@"6 - 7" from eslint-plugin-unused-imports@3.1.0
npm WARN     node_modules/eslint-plugin-unused-imports
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: @typescript-eslint/parser@7.4.0
npm WARN Found: eslint@9.2.0
npm WARN node_modules/eslint
npm WARN   dev eslint@"^9.2.0" from the root project
npm WARN   5 more (@eslint-community/eslint-utils, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^8.56.0" from @typescript-eslint/parser@7.4.0
npm WARN node_modules/@typescript-eslint/parser
npm WARN   peer @typescript-eslint/parser@"^7.0.0" from @typescript-eslint/eslint-plugin@7.4.0
npm WARN   node_modules/@typescript-eslint/eslint-plugin
npm WARN
npm WARN Conflicting peer dependency: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^8.56.0" from @typescript-eslint/parser@7.4.0
npm WARN   node_modules/@typescript-eslint/parser
npm WARN     peer @typescript-eslint/parser@"^7.0.0" from @typescript-eslint/eslint-plugin@7.4.0
npm WARN     node_modules/@typescript-eslint/eslint-plugin
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
npm ERR!
npm ERR! While resolving: eslint-plugin-react-hooks@4.6.0
npm ERR! Found: eslint@9.2.0
npm ERR! node_modules/eslint
npm ERR!   dev eslint@"^9.2.0" from the root project
npm ERR!   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm ERR!   node_modules/@eslint-community/eslint-utils
npm ERR!     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.4.0
npm ERR!     node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils
npm ERR!       @typescript-eslint/utils@"7.4.0" from @typescript-eslint/eslint-plugin@7.4.0
npm ERR!       node_modules/@typescript-eslint/eslint-plugin
npm ERR!         peerOptional @typescript-eslint/eslint-plugin@"6 - 7" from eslint-plugin-unused-imports@3.1.0
npm ERR!         node_modules/eslint-plugin-unused-imports
npm ERR!       1 more (@typescript-eslint/type-utils)
npm ERR!     @eslint-community/eslint-utils@"^4.2.0" from eslint@9.0.0
npm ERR!     2 more (@typescript-eslint/utils, eslint)
npm ERR!   4 more (eslint-config-prettier, eslint-config-turbo, ...)
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer eslint@"^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" from eslint-plugin-react-hooks@4.6.0
npm ERR! node_modules/eslint-plugin-react-hooks
npm ERR!
npm ERR! Conflicting peer dependency: eslint@8.57.0
npm ERR! node_modules/eslint
npm ERR!   peer eslint@"^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" from eslint-plugin-react-hooks@4.6.0
npm ERR!   node_modules/eslint-plugin-react-hooks
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
```

### 対応：eslintの入れ直し

```
$ npm uninstall eslint
npm WARN cleanup Failed to remove some directories [
npm WARN cleanup   [
npm WARN cleanup     'kartagraph-monorepo\\node_modules\\.turbo-windows-64-wzwOE5fA',
npm WARN cleanup     [Error: EPERM: operation not permitted, unlink 'D:\projects\kartagraph-monorepo\node_modules\.turbo-windows-64-wzwOE5fA\bin\turbo.exe'] {
npm WARN cleanup       errno: -4048,
npm WARN cleanup       code: 'EPERM',
npm WARN cleanup       syscall: 'unlink',
npm WARN cleanup       path: 'kartagraph-monorepo\\node_modules\\.turbo-windows-64-wzwOE5fA\\bin\\turbo.exe'
npm WARN cleanup     }
npm WARN cleanup   ]
npm WARN cleanup ]

added 7 packages, removed 28 packages, changed 128 packages, and audited 1589 packages in 1m

338 packages are looking for funding
  run `npm fund` for details

1 moderate severity vulnerability

To address all issues, run:
  npm audit fix

Run `npm audit` for details.
```

WARNは出るものの、エラーにはならなくなった。

```
$ npm i -D eslint@latest
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^8.56.0" from @typescript-eslint/eslint-plugin@7.8.0
npm WARN node_modules/@typescript-eslint/eslint-plugin
npm WARN   peerOptional @typescript-eslint/eslint-plugin@"6 - 7" from eslint-plugin-unused-imports@3.2.0
npm WARN   node_modules/eslint-plugin-unused-imports
npm WARN   1 more (typescript-eslint)
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^8.56.0" from @typescript-eslint/parser@7.8.0
npm WARN node_modules/@typescript-eslint/parser
npm WARN   peer @typescript-eslint/parser@"^7.0.0" from @typescript-eslint/eslint-plugin@7.8.0
npm WARN   node_modules/@typescript-eslint/eslint-plugin
npm WARN   1 more (typescript-eslint)
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" from eslint-plugin-import@2.29.1
npm WARN node_modules/eslint-plugin-import
npm WARN   dev eslint-plugin-import@"^2.29.1" from @kartagraph/eslint-config-custom@0.0.0
npm WARN   packages/eslint-config-custom
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" from eslint-plugin-react-hooks@4.6.2
npm WARN node_modules/eslint-plugin-react-hooks
npm WARN   dev eslint-plugin-react-hooks@"^4.6.2" from @kartagraph/eslint-config-custom@0.0.0
npm WARN   packages/eslint-config-custom
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"8" from eslint-plugin-unused-imports@3.2.0
npm WARN node_modules/eslint-plugin-unused-imports
npm WARN   dev eslint-plugin-unused-imports@"^3.2.0" from @kartagraph/eslint-config-custom@0.0.0
npm WARN   packages/eslint-config-custom
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: kartagraph-monorepo@0.0.0
npm WARN Found: eslint@8.57.0
npm WARN node_modules/eslint
npm WARN   peer eslint@"^6.0.0 || ^7.0.0 || >=8.0.0" from @eslint-community/eslint-utils@4.4.0
npm WARN   node_modules/@eslint-community/eslint-utils
npm WARN     @eslint-community/eslint-utils@"^4.4.0" from @typescript-eslint/utils@7.8.0
npm WARN     node_modules/@typescript-eslint/utils
npm WARN     1 more (eslint)
npm WARN   13 more (@typescript-eslint/eslint-plugin, ...)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peer eslint@"^8.56.0" from typescript-eslint@7.8.0
npm WARN node_modules/typescript-eslint
npm WARN   dev typescript-eslint@"^7.8.0" from @kartagraph/eslint-config-custom@0.0.0
npm WARN   packages/eslint-config-custom
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency
npm WARN ERESOLVE overriding peer dependency

added 6 packages, removed 9 packages, changed 5 packages, and audited 1590 packages in 2s

339 packages are looking for funding
  run `npm fund` for details

1 moderate severity vulnerability

To address all issues, run:
  npm audit fix

Run `npm audit` for details.
```

ただし、動かなくなった。
依存関係のあるプラグインを再インストールしてみる。

```
$ npm uninstall eslint-plugin-unused-imports eslint-plugin-import --force
```

```
$ npm i -D eslint-plugin-unused-imports eslint-plugin-import --legacy-peer-deps
```

eslintも再インストールしてみる。

```
$ npm i -D eslint@latest --legacy-peer-deps
```

VSCodeを再起動。
無事、lintが効くようになったことを確認した。


</div></details>

##  (2024.05.19 追記)typescripts-eslintの設定を recommended からstrictに変更した

[追加設定でおすすめされていたため。](https://typescript-eslint.io/getting-started#additional-configs)

```diff:default.js
export default tseslint.config({
  extends: [
    js.configs.recommended,
-    ...tseslint.configs.recommended,
+    ...tseslint.configs.strict,
+    ...tseslint.configs.stylistic
],
```

[recommended-configurations](https://typescript-eslint.io/users/configs#recommended-configurations) より

ルール|説明
--|--
recommended| 追加の設定なしで使用できる、コードの正確性のための推奨ルール。
recommended-type-checked| 推奨ルールに加えて、型情報を必要とする追加の推奨ルールを含む。
strict| 推奨ルールに加えて、より厳格で意見の分かれるルールを含み、バグの検出も可能。<br>**開発者のかなりの割合が TypeScript に高い熟練度を持っている場合にのみ推奨**
strict-type-checked| 厳格ルールに加えて、型情報を必要とする追加の厳格ルールを含む。
stylistic| 追加の設定なしで使用できるスタイリスティックルール。
stylistic-type-checked| スタイリスティックルールに加えて、型情報を必要とする追加のスタイリスティックルールを含む。

下記の記事が違いについてより詳細に解説していた。
[サイボウズ フロントエンド typescript-eslint v6 アップデートガイド](https://zenn.dev/cybozu_frontend/articles/ts-eslint-v6-guide)

## 2025.03.05 追記 Next.jsのeslintをFlat Configにした
各種プラグインのFlatConfigの対応も進んできている。

```js:base.js
import js from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";
import turboPlugin from "eslint-plugin-turbo";
import tseslint from "typescript-eslint";
import onlyWarn from "eslint-plugin-only-warn";

/**
 * A shared ESLint configuration for the repository.
 *
 * @type {import("eslint").Linter.Config}
 * */
export const config = [
  js.configs.recommended,
  eslintConfigPrettier,
  ...tseslint.configs.recommended,
  {
    plugins: {
      turbo: turboPlugin,
    },
    rules: {
      "turbo/no-undeclared-env-vars": "warn",
    },
  },
  {
    plugins: {
      onlyWarn,
    },
  },
  {
    ignores: ["dist/**"],
  },
];
```

createで作るデフォルトにプラグインを追加した例が下記。

```diff:next.js
import js from '@eslint/js';
import eslintConfigPrettier from 'eslint-config-prettier';
import tseslint from 'typescript-eslint';
import pluginReactHooks from 'eslint-plugin-react-hooks';
import pluginReact from 'eslint-plugin-react';
import globals from 'globals';
import pluginNext from '@next/eslint-plugin-next';
import { config as baseConfig } from './base.js';
+ import storybook from 'eslint-plugin-storybook';
+ import unuserdPlugin from 'eslint-plugin-unused-imports';
+ import sonarjs from 'eslint-plugin-sonarjs';
+ import importPlugin from 'eslint-plugin-import';
+ import { FlatCompat } from '@eslint/eslintrc';

const compat = new FlatCompat();

/**
 * A custom ESLint configuration for libraries that use Next.js.
 *
 * @type {import("eslint").Linter.Config}
 * */
export const nextJsConfig = [
  ...baseConfig,
  js.configs.recommended,
+   importPlugin.flatConfigs.recommended,
+   ...compat.extends('plugin:@conarti/feature-sliced/rules'),
+   ...storybook.configs['flat/recommended'],
  eslintConfigPrettier,
  ...tseslint.configs.recommended,
  {
    ...pluginReact.configs.flat.recommended,
    languageOptions: {
      ...pluginReact.configs.flat.recommended.languageOptions,
      globals: {
        ...globals.serviceworker,
      },
    },
  },
  {
    plugins: {
      '@next/next': pluginNext,
    },
    rules: {
      ...pluginNext.configs.recommended.rules,
      ...pluginNext.configs['core-web-vitals'].rules,
    },
  },
  {
    plugins: {
      'react-hooks': pluginReactHooks,
    },
    settings: { react: { version: 'detect' } },
    rules: {
      ...pluginReactHooks.configs.recommended.rules,
      // React scope no longer necessary with new JSX transform.
      'react/react-in-jsx-scope': 'off',
    },
  },

+  {
+    plugins: {
+      'unused-imports': unuserdPlugin,
+      sonarjs,
+    },
+    rules: {
+      semi: ['error', 'always'],
+      complexity: ['error', 7], // 複雑度の設定
+      // unuserd-importsのrecommended設定を適用
+      'no-unused-vars': 'off',
+      '@typescript-eslint/no-unused-vars': 'off',
+      'unused-imports/no-unused-imports': 'warn',
+      'unused-imports/no-unused-vars': [
+        'warn',
+        {
+          vars: 'all',
+          varsIgnorePattern: '^_',
+          args: 'after-used',
+          argsIgnorePattern: '^_',
+        },
+      ],
+      // ここまで unuserd-importsのrecommended設定を適用
+      'import/order': [
+        'warn',
+        {
+          groups: [
+            'builtin',
+            'external',
+            'internal',
+            'parent',
+            'sibling',
+            'index',
+            'object',
+            'type',
+          ], // importの並び順の設定
+          pathGroupsExcludedImportTypes: ['builtin'],
+          pathGroups: [{ pattern: '@src/**', group: 'parent', position: 'before' }], // エイリアスの位置を指定
+          alphabetize: { order: 'asc' }, // グループ内のソート順
+        },
+      ],
+      'import/prefer-default-export': ['off'],
+      'import/extensions': ['off'],
+      'import/no-unresolved': ['off'],
+      'react/prop-types': ['off'],
+      'turbo/no-undeclared-env-vars': ['off'],
+    },
+  },
];
```


## 参考

[ESLintのFlat Config移行でやって良かったこと](https://zenn.dev/mkizka/articles/7ff4f256e38401)
[ESLint v8.56.0 の `reportUnusedDisableDirectives` とは何か？](https://zenn.dev/teppeis/articles/2023-12-eslint-report-unused-disable-directives)
[ESLintの設定を視覚化してくれるESLint Config Inspector](https://qiita.com/KokiSakano/items/55fc416cbaa6edb2bf20)

[findコマンドで-execオプションを使用する時の最後の「{} ;」ってなんだっけ？](https://qiita.com/legitwhiz/items/e609537fb6226081f5b5)

[サイボウズ フロントエンド typescript-eslint v6 アップデートガイド](https://zenn.dev/cybozu_frontend/articles/ts-eslint-v6-guide)

[ESLintをeslintrcからFlat Configに移行する際の最新手順 (2024年10月更新)](https://qiita.com/ljourm/items/0c98f342d437ed3a8563)