Skip to content

Commit 17a6349

Browse files
committed
add eslint-plugin-import-x rules
1 parent 7ec6701 commit 17a6349

10 files changed

Lines changed: 349 additions & 251 deletions

File tree

eslint.config.mjs

Lines changed: 144 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
1+
import * as EslintCompat from '@eslint/compat'
12
import EslintJs from '@eslint/js'
2-
import {
3-
fixupPluginRules,
4-
} from '@eslint/compat'
5-
import StylisticJs from '@stylistic/eslint-plugin'
6-
import TsEslint from 'typescript-eslint'
73

84
import ReactNativeEslintConfig from '@react-native/eslint-config'
9-
import ReactNativeEslintPlugin from 'eslint-plugin-react-native'
5+
6+
import StylisticJs from '@stylistic/eslint-plugin'
7+
8+
import * as EslintImportResolverTypeScript from 'eslint-import-resolver-typescript'
9+
10+
import * as EslintPluginImportX from 'eslint-plugin-import-x'
11+
1012
import ReactEslintPlugin from 'eslint-plugin-react'
11-
import ReactHooksEslintPlugin from 'eslint-plugin-react-hooks'
13+
14+
import * as ReactHooksEslintPlugin from 'eslint-plugin-react-hooks'
15+
16+
import ReactNativeEslintPlugin from 'eslint-plugin-react-native'
1217

1318
import Globals from 'globals'
1419

20+
import * as TypeScriptEslint from 'typescript-eslint'
21+
1522
export default [
1623

1724
{
@@ -23,16 +30,85 @@ export default [
2330

2431
EslintJs.configs.recommended,
2532

33+
EslintPluginImportX.importX.flatConfigs.recommended,
34+
EslintPluginImportX.importX.flatConfigs.typescript,
35+
2636
{
27-
plugins: {
28-
'@stylistic': StylisticJs,
29-
},
3037
rules: {
3138
'consistent-return': 'error',
3239
'eol-last': 'error',
3340
'semi': 'off',
3441
'yoda': 'error',
3542

43+
'import-x/first': 'error',
44+
'import-x/newline-after-import': [
45+
'error',
46+
{
47+
'count': 1,
48+
'considerComments': true,
49+
},
50+
],
51+
'import-x/no-cycle': 'error',
52+
'import-x/order': [
53+
'error',
54+
{
55+
'alphabetize': {
56+
'order': 'asc',
57+
},
58+
/**
59+
* I want to distinct module import, not only the group
60+
* Ommitting this prop is not force me to put new empty line each import tho
61+
*/
62+
// 'consolidateIslands': 'inside-groups',
63+
'distinctGroup': false,
64+
'newlines-between': 'always-and-inside-groups',
65+
'named': {
66+
'enabled': true,
67+
'cjsExports': true,
68+
'export': true,
69+
'import': true,
70+
'require': true,
71+
'types': 'types-last',
72+
},
73+
'groups': [
74+
'builtin',
75+
'external',
76+
'internal',
77+
'parent',
78+
'sibling',
79+
'index',
80+
],
81+
'pathGroups': [
82+
{
83+
'pattern': 'react',
84+
'group': 'builtin',
85+
'position': 'after',
86+
},
87+
{
88+
'pattern': 'react-native',
89+
'group': 'builtin',
90+
'position': 'after',
91+
},
92+
{
93+
'pattern': '@storybook/**',
94+
'group': 'builtin',
95+
'position': 'after',
96+
},
97+
],
98+
'pathGroupsExcludedImportTypes': [
99+
'builtin',
100+
],
101+
'warnOnUnassignedImports': true,
102+
},
103+
],
104+
},
105+
},
106+
107+
{
108+
plugins: {
109+
'@stylistic': StylisticJs,
110+
},
111+
rules: {
36112
'@stylistic/block-spacing': 'error',
37113
'@stylistic/brace-style': [
38114
'error',
@@ -83,12 +159,12 @@ export default [
83159
'if': {
84160
'after': false,
85161
},
86-
'catch': {
162+
'for': {
87163
'after': false,
88-
'before': true,
89164
},
90-
'for': {
165+
'catch': {
91166
'after': false,
167+
'before': true,
92168
},
93169
},
94170
},
@@ -119,6 +195,24 @@ export default [
119195
'ignoreComments': true,
120196
},
121197
],
198+
'@stylistic/object-curly-newline': [
199+
'error',
200+
{
201+
'ObjectExpression': {
202+
'multiline': true,
203+
'consistent': true,
204+
},
205+
'ObjectPattern': {
206+
'multiline': true,
207+
'consistent': true,
208+
},
209+
'ExportDeclaration': 'always',
210+
'ImportDeclaration': 'always',
211+
'TSTypeLiteral': 'always',
212+
'TSInterfaceBody': 'always',
213+
'TSEnumBody': 'always',
214+
},
215+
],
122216
'@stylistic/object-curly-spacing': [
123217
'warn',
124218
'always',
@@ -137,8 +231,8 @@ export default [
137231
{
138232
'anonymous': 'never',
139233
'asyncArrow': 'always', // valid: async () => {} | error: async() => {}
140-
'catch': 'never',
141234
'named': 'never',
235+
"catch": "never",
142236
},
143237
],
144238
'@stylistic/space-infix-ops': [
@@ -154,11 +248,10 @@ export default [
154248
},
155249
},
156250

157-
...TsEslint.configs.recommendedTypeChecked.map(conf => ({
251+
...TypeScriptEslint.configs.recommendedTypeChecked.map(conf => ({
158252
...conf,
159253
files: ['**/*.ts', '**/*.tsx', '**/*.mts'],
160254
})),
161-
162255
{
163256
files: [
164257
'**/*.ts',
@@ -173,6 +266,15 @@ export default [
173266
'@typescript-eslint/no-unsafe-argument': 'off',
174267
'@typescript-eslint/no-unsafe-assignment': 'off',
175268
},
269+
languageOptions: {
270+
parserOptions: {
271+
project: [
272+
'./example/tsconfig.json',
273+
'./package/tsconfig.json',
274+
],
275+
tsconfigRootDir: import.meta.dirname,
276+
},
277+
},
176278
},
177279

178280
{
@@ -192,8 +294,8 @@ export default [
192294
},
193295
plugins: {
194296
...ReactEslintPlugin.configs.flat['jsx-runtime'].plugins,
195-
'react-hooks': fixupPluginRules(ReactHooksEslintPlugin),
196-
'react-native': fixupPluginRules(ReactNativeEslintPlugin),
297+
'react-hooks': EslintCompat.fixupPluginRules(ReactHooksEslintPlugin),
298+
'react-native': EslintCompat.fixupPluginRules(ReactNativeEslintPlugin),
197299
},
198300
languageOptions: {
199301
...ReactEslintPlugin.configs.flat['jsx-runtime'].languageOptions,
@@ -231,15 +333,30 @@ export default [
231333
},
232334

233335
{
234-
languageOptions: {
235-
ecmaVersion: 2020,
236-
parserOptions: {
237-
project: [
238-
'./example/tsconfig.json',
239-
'./package/tsconfig.json',
240-
],
241-
tsconfigRootDir: import.meta.dirname,
242-
},
336+
files: [
337+
'./example/**/*.{ts,tsx}',
338+
],
339+
settings: {
340+
'import-x/resolver-next': [
341+
EslintImportResolverTypeScript.createTypeScriptImportResolver({
342+
alwaysTryTypes: true,
343+
project: './example/tsconfig.json',
344+
}),
345+
],
346+
},
347+
},
348+
349+
{
350+
files: [
351+
'./package/**/*.{ts,tsx}',
352+
],
353+
settings: {
354+
'import-x/resolver-next': [
355+
EslintImportResolverTypeScript.createTypeScriptImportResolver({
356+
alwaysTryTypes: true,
357+
project: './package/tsconfig.json',
358+
}),
359+
],
243360
},
244361
},
245362

example/App.tsx

Lines changed: 0 additions & 39 deletions
This file was deleted.

example/__tests__/App.test.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
*/
44

55
// import React from 'react';
6-
import ReactTestRenderer from 'react-test-renderer';
7-
import App from '../App';
6+
import * as ReactTestRenderer from 'react-test-renderer';
7+
8+
import {
9+
ExampleApp,
10+
} from '../src/ExampleApp';
811

912
test('renders correctly', async () => {
1013
await ReactTestRenderer.act(() => {
11-
ReactTestRenderer.create(<App />);
14+
ReactTestRenderer.create(<ExampleApp />);
1215
});
1316
});

example/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import {
66
AppRegistry,
77
} from 'react-native'
88

9-
import {
10-
ExampleApp,
11-
} from './src/ExampleApp'
12-
139
import {
1410
name as appName,
1511
} from './app.json'
1612

13+
import {
14+
ExampleApp,
15+
} from './src/ExampleApp'
16+
1717
AppRegistry.registerComponent(appName, () => ExampleApp);

example/src/screens/ping-runner/PingRunnerScreen.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@ import {
99
Pressable,
1010
StyleSheet,
1111
Text,
12-
useColorScheme,
1312
View,
1413
VirtualizedList,
14+
useColorScheme,
1515
type VirtualizedListProps,
1616
} from 'react-native'
1717

18-
import {
19-
useSafeAreaInsets,
20-
} from 'react-native-safe-area-context'
21-
2218
import {
2319
ICMP,
2420
PingStatus,
2521
useICMP,
2622
} from 'ping-react-native'
2723

24+
import {
25+
useSafeAreaInsets,
26+
} from 'react-native-safe-area-context'
27+
2828
import {
2929
type NavigationType,
3030
} from '@/types'

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@
1313
"type-check": "tsc --project package/tsconfig.json && tsc --project example/tsconfig.json"
1414
},
1515
"devDependencies": {
16-
"@eslint/compat": "^1.3.2",
17-
"@eslint/js": "^9.33.0",
16+
"@eslint/compat": "^1.4.0",
17+
"@eslint/js": "^9.36.0",
1818
"@react-native/eslint-config": "0.81.4",
1919
"@react-native/typescript-config": "0.81.4",
2020
"@stylistic/eslint-plugin": "^5.2.3",
2121
"@types/node": "^22",
22-
"eslint": "^9.33.0",
22+
"eslint": "^9.36.0",
2323
"eslint-import-resolver-typescript": "^4.4.4",
2424
"eslint-plugin-import-x": "^4.16.1",
2525
"eslint-plugin-react": "^7.37.5",
2626
"eslint-plugin-react-hooks": "^5.2.0",
2727
"eslint-plugin-react-native": "^5.0.0",
28-
"globals": "^16.3.0",
28+
"globals": "^16.4.0",
2929
"typescript": "5.9.2",
30-
"typescript-eslint": "^8.39.0"
30+
"typescript-eslint": "^8.44.1"
3131
},
3232
"engines": {
3333
"node": ">=22",

0 commit comments

Comments
 (0)