|
1 | 1 | // eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
2 |
| -/// <reference path="./eslint-typegen.d.ts" /> |
| 2 | +/// <reference path="./eslint-typegen-generated.d.ts" /> |
3 | 3 |
|
4 |
| -import { FlatCompat } from "@eslint/eslintrc"; |
5 | 4 | import js from "@eslint/js";
|
6 |
| -import type { Linter } from "eslint"; |
| 5 | +import { defineConfig, globalIgnores } from "eslint/config"; |
7 | 6 | import gitignore from "eslint-config-flat-gitignore";
|
| 7 | +// @ts-expect-error type definition not exists |
8 | 8 | import jsxA11y from "eslint-plugin-jsx-a11y";
|
9 | 9 | import react from "eslint-plugin-react";
|
| 10 | +import reactHooks from "eslint-plugin-react-hooks"; |
10 | 11 | import reactRefresh from "eslint-plugin-react-refresh";
|
11 | 12 | import simpleImportSort from "eslint-plugin-simple-import-sort";
|
12 | 13 | import typegen from "eslint-typegen";
|
13 | 14 | import globals from "globals";
|
14 |
| -import type { InfiniteDepthConfigWithExtends } from "typescript-eslint"; |
15 | 15 | import tseslint from "typescript-eslint";
|
16 | 16 |
|
17 | 17 | const tsFiles = "**/*.{ts,tsx,mts,cts}";
|
18 | 18 | const jsFiles = "**/*.{js,jsx,mjs,cjs}";
|
19 | 19 | const jsxFiles = "**/*.{jsx,tsx}";
|
20 | 20 |
|
21 |
| -const compat = new FlatCompat(); |
22 |
| - |
23 |
| -const config = [ |
24 |
| - gitignore(), |
25 |
| - { |
26 |
| - files: [jsFiles], |
27 |
| - ...js.configs.recommended, |
28 |
| - }, |
29 |
| - { |
30 |
| - ignores: ["app/generated/**"], |
31 |
| - }, |
32 |
| - { |
33 |
| - files: [tsFiles], |
34 |
| - extends: [ |
35 |
| - ...tseslint.configs.recommendedTypeChecked, |
36 |
| - ...tseslint.configs.stylisticTypeChecked, |
37 |
| - ], |
38 |
| - languageOptions: { |
39 |
| - parserOptions: { |
40 |
| - projectService: true, |
41 |
| - }, |
| 21 | +export default typegen( |
| 22 | + defineConfig( |
| 23 | + gitignore(), |
| 24 | + globalIgnores(["app/generated/**"]), |
| 25 | + { |
| 26 | + files: [jsFiles], |
| 27 | + ...js.configs.recommended, |
42 | 28 | },
|
43 |
| - rules: { |
44 |
| - "@typescript-eslint/adjacent-overload-signatures": "off", |
45 |
| - "@typescript-eslint/array-type": [ |
46 |
| - "error", |
47 |
| - { |
48 |
| - default: "array-simple", |
49 |
| - }, |
| 29 | + { |
| 30 | + files: [tsFiles], |
| 31 | + // @ts-expect-error type mismatch between eslint and typescript-eslint |
| 32 | + extends: [ |
| 33 | + ...tseslint.configs.recommendedTypeChecked, |
| 34 | + ...tseslint.configs.stylisticTypeChecked, |
50 | 35 | ],
|
51 |
| - "@typescript-eslint/class-literal-property-style": "off", |
52 |
| - "@typescript-eslint/consistent-generic-constructors": "off", |
53 |
| - "@typescript-eslint/consistent-indexed-object-style": "off", |
54 |
| - "@typescript-eslint/consistent-type-assertions": "error", |
55 |
| - "@typescript-eslint/consistent-type-definitions": "off", |
56 |
| - "@typescript-eslint/consistent-type-exports": "error", |
57 |
| - "@typescript-eslint/consistent-type-imports": [ |
58 |
| - "error", |
59 |
| - { fixStyle: "separate-type-imports" }, |
60 |
| - ], |
61 |
| - "@typescript-eslint/no-confusing-non-null-assertion": "off", |
62 |
| - "@typescript-eslint/no-deprecated": "warn", |
63 |
| - "@typescript-eslint/no-duplicate-enum-values": "off", |
64 |
| - "@typescript-eslint/no-import-type-side-effects": "error", |
65 |
| - "@typescript-eslint/no-non-null-assertion": "warn", |
66 |
| - "@typescript-eslint/no-unsafe-declaration-merging": "off", |
67 |
| - "@typescript-eslint/prefer-function-type": "off", |
68 |
| - "@typescript-eslint/promise-function-async": "error", |
69 |
| - "@typescript-eslint/no-restricted-imports": [ |
70 |
| - "error", |
71 |
| - { |
72 |
| - paths: [ |
73 |
| - { |
74 |
| - allowTypeImports: true, |
75 |
| - name: "@mantine/core", |
76 |
| - importNames: ["TextInput"], |
77 |
| - message: |
78 |
| - "Please use TextInput from '~/components/mantine/TextInput' instead.", |
79 |
| - }, |
80 |
| - { |
81 |
| - allowTypeImports: true, |
82 |
| - name: "@mantine/core", |
83 |
| - importNames: ["Fieldset"], |
84 |
| - message: |
85 |
| - "Please use Fieldset from '~/components/mantine/Fieldset' instead.", |
86 |
| - }, |
87 |
| - ], |
| 36 | + languageOptions: { |
| 37 | + parserOptions: { |
| 38 | + projectService: true, |
88 | 39 | },
|
89 |
| - ], |
90 |
| - }, |
91 |
| - }, |
92 |
| - { |
93 |
| - files: [jsFiles, tsFiles], |
94 |
| - languageOptions: { |
95 |
| - sourceType: "module", |
96 |
| - }, |
97 |
| - plugins: { "simple-import-sort": simpleImportSort }, |
98 |
| - rules: { |
99 |
| - "simple-import-sort/imports": "error", |
| 40 | + }, |
| 41 | + rules: { |
| 42 | + "@typescript-eslint/adjacent-overload-signatures": "off", |
| 43 | + "@typescript-eslint/array-type": [ |
| 44 | + "error", |
| 45 | + { |
| 46 | + default: "array-simple", |
| 47 | + }, |
| 48 | + ], |
| 49 | + "@typescript-eslint/class-literal-property-style": "off", |
| 50 | + "@typescript-eslint/consistent-generic-constructors": "off", |
| 51 | + "@typescript-eslint/consistent-indexed-object-style": "off", |
| 52 | + "@typescript-eslint/consistent-type-assertions": "error", |
| 53 | + "@typescript-eslint/consistent-type-definitions": "off", |
| 54 | + "@typescript-eslint/consistent-type-exports": "error", |
| 55 | + "@typescript-eslint/consistent-type-imports": [ |
| 56 | + "error", |
| 57 | + { fixStyle: "separate-type-imports" }, |
| 58 | + ], |
| 59 | + "@typescript-eslint/no-confusing-non-null-assertion": "off", |
| 60 | + "@typescript-eslint/no-deprecated": "warn", |
| 61 | + "@typescript-eslint/no-duplicate-enum-values": "off", |
| 62 | + "@typescript-eslint/no-import-type-side-effects": "error", |
| 63 | + "@typescript-eslint/no-non-null-assertion": "warn", |
| 64 | + "@typescript-eslint/no-unsafe-declaration-merging": "off", |
| 65 | + "@typescript-eslint/prefer-function-type": "off", |
| 66 | + "@typescript-eslint/promise-function-async": "error", |
| 67 | + "@typescript-eslint/no-restricted-imports": [ |
| 68 | + "error", |
| 69 | + { |
| 70 | + paths: [ |
| 71 | + { |
| 72 | + allowTypeImports: true, |
| 73 | + name: "@mantine/core", |
| 74 | + importNames: ["TextInput"], |
| 75 | + message: |
| 76 | + "Please use TextInput from '~/components/mantine/TextInput' instead.", |
| 77 | + }, |
| 78 | + { |
| 79 | + allowTypeImports: true, |
| 80 | + name: "@mantine/core", |
| 81 | + importNames: ["Fieldset"], |
| 82 | + message: |
| 83 | + "Please use Fieldset from '~/components/mantine/Fieldset' instead.", |
| 84 | + }, |
| 85 | + ], |
| 86 | + }, |
| 87 | + ], |
| 88 | + }, |
100 | 89 | },
|
101 |
| - }, |
102 |
| - { |
103 |
| - files: [jsxFiles], |
104 |
| - extends: [ |
105 |
| - // @ts-expect-error 型が合わない |
106 |
| - react.configs.flat.recommended, |
107 |
| - // @ts-expect-error 型が合わない |
108 |
| - react.configs.flat["jsx-runtime"], |
109 |
| - ...compat.extends("plugin:react-hooks/recommended"), |
110 |
| - reactRefresh.configs.vite, |
111 |
| - jsxA11y.flatConfigs.recommended, |
112 |
| - ], |
113 |
| - languageOptions: { |
114 |
| - globals: { |
115 |
| - ...globals.browser, |
| 90 | + { |
| 91 | + files: [jsFiles, tsFiles], |
| 92 | + languageOptions: { |
| 93 | + sourceType: "module", |
| 94 | + }, |
| 95 | + plugins: { "simple-import-sort": simpleImportSort }, |
| 96 | + rules: { |
| 97 | + "simple-import-sort/imports": "error", |
116 | 98 | },
|
117 | 99 | },
|
118 |
| - rules: { |
119 |
| - // this is for form callback |
120 |
| - "@typescript-eslint/no-misused-promises": [ |
121 |
| - "error", |
122 |
| - { |
123 |
| - checksVoidReturn: { |
124 |
| - attributes: false, |
125 |
| - }, |
126 |
| - }, |
| 100 | + { |
| 101 | + files: [jsxFiles], |
| 102 | + extends: [ |
| 103 | + react.configs.flat.recommended, |
| 104 | + react.configs.flat["jsx-runtime"], |
| 105 | + reactHooks.configs["recommended-latest"], |
| 106 | + reactRefresh.configs.vite, |
| 107 | + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access |
| 108 | + jsxA11y.flatConfigs.recommended, |
127 | 109 | ],
|
128 |
| - "react/button-has-type": "error", |
129 |
| - "react/iframe-missing-sandbox": "error", |
130 |
| - "react/jsx-boolean-value": "error", |
131 |
| - "react/jsx-curly-brace-presence": ["error", "never"], |
132 |
| - "react/jsx-no-target-blank": ["error", { allowReferrer: true }], |
133 |
| - "react/prop-types": "off", |
134 |
| - "react/self-closing-comp": "error", |
135 |
| - "react/jsx-sort-props": "error", |
136 |
| - "react-refresh/only-export-components": [ |
137 |
| - "error", |
138 |
| - { |
139 |
| - allowExportNames: ["meta", "links", "headers", "loader", "action"], |
| 110 | + languageOptions: { |
| 111 | + globals: { |
| 112 | + ...globals.browser, |
140 | 113 | },
|
141 |
| - ], |
142 |
| - }, |
143 |
| - settings: { |
144 |
| - react: { |
145 |
| - version: "detect", |
146 | 114 | },
|
147 |
| - }, |
148 |
| - }, |
149 |
| - { |
150 |
| - files: ["**/*.browser.test.{js,jsx,ts,tsx}"], |
151 |
| - rules: { |
152 |
| - "@typescript-eslint/no-restricted-imports": [ |
153 |
| - "error", |
154 |
| - { |
155 |
| - paths: [ |
156 |
| - { |
157 |
| - allowTypeImports: true, |
158 |
| - name: "vitest-browser-react", |
159 |
| - importNames: ["render"], |
160 |
| - message: |
161 |
| - "Please import from '<root>/test/test-react' instead of 'vitest-browser-react'.", |
| 115 | + rules: { |
| 116 | + // this is for form callback |
| 117 | + "@typescript-eslint/no-misused-promises": [ |
| 118 | + "error", |
| 119 | + { |
| 120 | + checksVoidReturn: { |
| 121 | + attributes: false, |
162 | 122 | },
|
163 |
| - ], |
| 123 | + }, |
| 124 | + ], |
| 125 | + "react/button-has-type": "error", |
| 126 | + "react/iframe-missing-sandbox": "error", |
| 127 | + "react/jsx-boolean-value": "error", |
| 128 | + "react/jsx-curly-brace-presence": ["error", "never"], |
| 129 | + "react/jsx-no-target-blank": ["error", { allowReferrer: true }], |
| 130 | + "react/prop-types": "off", |
| 131 | + "react/self-closing-comp": "error", |
| 132 | + "react/jsx-sort-props": "error", |
| 133 | + "react-refresh/only-export-components": [ |
| 134 | + "error", |
| 135 | + { |
| 136 | + allowExportNames: ["meta", "links", "headers", "loader", "action"], |
| 137 | + }, |
| 138 | + ], |
| 139 | + }, |
| 140 | + settings: { |
| 141 | + react: { |
| 142 | + version: "detect", |
164 | 143 | },
|
165 |
| - ], |
| 144 | + }, |
| 145 | + }, |
| 146 | + { |
| 147 | + files: ["**/*.browser.test.{js,jsx,ts,tsx}"], |
| 148 | + rules: { |
| 149 | + "@typescript-eslint/no-restricted-imports": [ |
| 150 | + "error", |
| 151 | + { |
| 152 | + paths: [ |
| 153 | + { |
| 154 | + allowTypeImports: true, |
| 155 | + name: "vitest-browser-react", |
| 156 | + importNames: ["render"], |
| 157 | + message: |
| 158 | + "Please import from '<root>/test/test-react' instead of 'vitest-browser-react'.", |
| 159 | + }, |
| 160 | + ], |
| 161 | + }, |
| 162 | + ], |
| 163 | + }, |
166 | 164 | },
|
167 |
| - }, |
168 |
| -] satisfies Array< |
169 |
| - Linter.Config & { |
170 |
| - extends?: InfiniteDepthConfigWithExtends; |
171 |
| - } |
172 |
| ->; |
173 |
| - |
174 |
| -// @ts-expect-error TypeScript は ./eslint-typegen を見てしまう |
175 |
| -// 実際のnode_modules 内の型定義には反していない |
176 |
| -export default typegen( |
177 |
| - tseslint.config( |
178 |
| - // @ts-expect-error 型が合わないが、実際には動作する |
179 |
| - config, |
180 | 165 | ),
|
| 166 | + { |
| 167 | + dtsPath: "./eslint-typegen-generated.d.ts", |
| 168 | + }, |
181 | 169 | );
|
0 commit comments