eslint-plugin-code-style 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/index.js +244 -244
- package/package.json +1 -5
- package/AGENTS.md +0 -1387
- package/CHANGELOG.md +0 -2087
- package/CLAUDE.md +0 -12
- package/docs/rules/README.md +0 -31
- package/docs/rules/arrays.md +0 -107
- package/docs/rules/arrow-functions.md +0 -115
- package/docs/rules/call-expressions.md +0 -275
- package/docs/rules/classes.md +0 -88
- package/docs/rules/comments.md +0 -42
- package/docs/rules/components.md +0 -330
- package/docs/rules/control-flow.md +0 -448
- package/docs/rules/functions.md +0 -232
- package/docs/rules/hooks.md +0 -147
- package/docs/rules/imports-exports.md +0 -383
- package/docs/rules/jsx.md +0 -518
- package/docs/rules/objects.md +0 -224
- package/docs/rules/react.md +0 -175
- package/docs/rules/spacing.md +0 -61
- package/docs/rules/strings.md +0 -92
- package/docs/rules/typescript.md +0 -482
- package/docs/rules/variables.md +0 -32
package/docs/rules/hooks.md
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# Hook Rules
|
|
2
|
-
|
|
3
|
-
### `hook-callback-format`
|
|
4
|
-
|
|
5
|
-
**What it does:** Enforces consistent multi-line formatting for React hooks that take a callback and dependency array (useEffect, useCallback, useMemo, useLayoutEffect).
|
|
6
|
-
|
|
7
|
-
**Why use it:** Hooks with callbacks and dependencies are complex. Multi-line formatting makes the callback, return cleanup, and dependencies clearly visible.
|
|
8
|
-
|
|
9
|
-
```javascript
|
|
10
|
-
// ✅ Good — callback and deps clearly separated
|
|
11
|
-
useEffect(
|
|
12
|
-
() => {
|
|
13
|
-
fetchData();
|
|
14
|
-
},
|
|
15
|
-
[userId],
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
useCallback(
|
|
19
|
-
() => {
|
|
20
|
-
handleSubmit(data);
|
|
21
|
-
},
|
|
22
|
-
[data, handleSubmit],
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
useMemo(
|
|
26
|
-
() => expensiveCalculation(items),
|
|
27
|
-
[items],
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
// ✅ Good — cleanup function visible
|
|
31
|
-
useEffect(
|
|
32
|
-
() => {
|
|
33
|
-
const subscription = subscribe();
|
|
34
|
-
|
|
35
|
-
return () => subscription.unsubscribe();
|
|
36
|
-
},
|
|
37
|
-
[subscribe],
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
// ❌ Bad — everything crammed on one line
|
|
41
|
-
useEffect(() => { fetchData(); }, [userId]);
|
|
42
|
-
|
|
43
|
-
// ❌ Bad — hard to see dependencies
|
|
44
|
-
useCallback(() => { handleSubmit(data); }, [data, handleSubmit]);
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
### `hook-deps-per-line`
|
|
50
|
-
|
|
51
|
-
**What it does:** When a hook's dependency array exceeds the threshold (default: 2), each dependency goes on its own line.
|
|
52
|
-
|
|
53
|
-
**Why use it:** Long dependency arrays are hard to scan and diff. One per line makes it easy to see what changed and catch missing/extra dependencies.
|
|
54
|
-
|
|
55
|
-
```javascript
|
|
56
|
-
// ✅ Good — 2 or fewer deps stay inline
|
|
57
|
-
useEffect(() => {}, [userId]);
|
|
58
|
-
useEffect(() => {}, [userId, token]);
|
|
59
|
-
|
|
60
|
-
// ✅ Good — 3+ deps get one per line
|
|
61
|
-
useEffect(
|
|
62
|
-
() => {},
|
|
63
|
-
[
|
|
64
|
-
userId,
|
|
65
|
-
token,
|
|
66
|
-
refreshToken,
|
|
67
|
-
],
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
useCallback(
|
|
71
|
-
() => handleSubmit(data),
|
|
72
|
-
[
|
|
73
|
-
data,
|
|
74
|
-
handleSubmit,
|
|
75
|
-
validateForm,
|
|
76
|
-
showError,
|
|
77
|
-
],
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
// ❌ Bad — too many deps on one line
|
|
81
|
-
useEffect(() => {}, [userId, token, refreshToken, apiUrl]);
|
|
82
|
-
|
|
83
|
-
// ❌ Bad — deps should be one per line when expanded
|
|
84
|
-
useEffect(() => {}, [
|
|
85
|
-
userId, token, refreshToken,
|
|
86
|
-
]);
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
**Options:**
|
|
90
|
-
|
|
91
|
-
| Option | Type | Default | Description |
|
|
92
|
-
|--------|------|---------|-------------|
|
|
93
|
-
| `maxDeps` | `integer` | `2` | Maximum dependencies to keep on single line |
|
|
94
|
-
|
|
95
|
-
```javascript
|
|
96
|
-
// Example: Allow up to 3 dependencies on single line
|
|
97
|
-
"code-style/hook-deps-per-line": ["error", { maxDeps: 3 }]
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
<br />
|
|
101
|
-
|
|
102
|
-
### `use-state-naming-convention`
|
|
103
|
-
|
|
104
|
-
**What it does:** Enforces boolean useState variables to start with valid prefixes (is, has, with, without).
|
|
105
|
-
|
|
106
|
-
**Why use it:** Consistent boolean state naming makes code more predictable and self-documenting. When you see `isLoading`, you immediately know it's a boolean state.
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
// ✅ Good — boolean state with proper prefix
|
|
110
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
111
|
-
const [hasError, setHasError] = useState<boolean>(false);
|
|
112
|
-
const [isAuthenticated, setIsAuthenticated] = useState(true);
|
|
113
|
-
const [withBorder, setWithBorder] = useState(false);
|
|
114
|
-
|
|
115
|
-
// ❌ Bad — boolean state without prefix
|
|
116
|
-
const [loading, setLoading] = useState(false);
|
|
117
|
-
const [authenticated, setAuthenticated] = useState<boolean>(true);
|
|
118
|
-
const [error, setError] = useState<boolean>(false);
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
**Customization Options:**
|
|
122
|
-
|
|
123
|
-
| Option | Type | Default | Description |
|
|
124
|
-
|--------|------|---------|-------------|
|
|
125
|
-
| `booleanPrefixes` | `string[]` | `["is", "has", "with", "without"]` | Replace default prefixes entirely |
|
|
126
|
-
| `extendBooleanPrefixes` | `string[]` | `[]` | Add additional prefixes to defaults |
|
|
127
|
-
| `allowPastVerbBoolean` | `boolean` | `false` | Allow past verb names without prefix (disabled, selected) |
|
|
128
|
-
| `allowContinuousVerbBoolean` | `boolean` | `false` | Allow continuous verb names without prefix (loading, saving) |
|
|
129
|
-
|
|
130
|
-
```javascript
|
|
131
|
-
// Example: Allow "loading" and "disabled" without prefix
|
|
132
|
-
"code-style/use-state-naming-convention": ["error", {
|
|
133
|
-
allowPastVerbBoolean: true,
|
|
134
|
-
allowContinuousVerbBoolean: true
|
|
135
|
-
}]
|
|
136
|
-
|
|
137
|
-
// Example: Add "should" prefix
|
|
138
|
-
"code-style/use-state-naming-convention": ["error", {
|
|
139
|
-
extendBooleanPrefixes: ["should"]
|
|
140
|
-
}]
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
<br />
|
|
144
|
-
|
|
145
|
-
---
|
|
146
|
-
|
|
147
|
-
[← Back to Rules Index](./README.md) | [← Back to Main README](../../README.md)
|
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
# Import/Export Rules
|
|
2
|
-
|
|
3
|
-
### `absolute-imports-only`
|
|
4
|
-
|
|
5
|
-
**What it does:** Enforces importing from folder index files using absolute paths (aliases like `@/`) instead of relative paths or deep file imports. Files within the same module folder must use relative imports (`./` or `../`) instead of absolute paths to avoid circular dependencies through the index file. Auto-fixes absolute imports to own module folder into relative paths. 🔧
|
|
6
|
-
|
|
7
|
-
**Why use it:**
|
|
8
|
-
- Absolute imports are cleaner than `../../../components`
|
|
9
|
-
- Index imports create a public API for each folder
|
|
10
|
-
- Refactoring file locations doesn't break imports
|
|
11
|
-
- Encourages proper module organization
|
|
12
|
-
- Relative imports within the same module folder avoid circular dependencies
|
|
13
|
-
|
|
14
|
-
```javascript
|
|
15
|
-
// ✅ Good — import from index files using alias
|
|
16
|
-
import { Button, Input } from "@/components";
|
|
17
|
-
import { useAuth, useUser } from "@/hooks";
|
|
18
|
-
import { fetchUsers } from "@/apis";
|
|
19
|
-
import { formatDate } from "@/utils";
|
|
20
|
-
|
|
21
|
-
// ✅ Good — assets allow deep imports by default
|
|
22
|
-
import logo from "@/assets/images/logo.png";
|
|
23
|
-
|
|
24
|
-
// ✅ Good — relative import within the same module folder (siblings)
|
|
25
|
-
// File: utils/formatters.js
|
|
26
|
-
import { isNumber } from "./validators";
|
|
27
|
-
|
|
28
|
-
// ✅ Good — relative import within the same module folder (nested)
|
|
29
|
-
// File: data/auth/forget-password/index.ts
|
|
30
|
-
import { guestLoginData } from "../../login/guest";
|
|
31
|
-
|
|
32
|
-
// ❌ Bad — absolute import to own module folder (should use relative)
|
|
33
|
-
// File: data/auth/forget-password/index.ts
|
|
34
|
-
import { guestLoginData } from "@/data";
|
|
35
|
-
// → use relative import instead: import { guestLoginData } from "../../login/guest";
|
|
36
|
-
|
|
37
|
-
// ❌ Bad — relative imports across different folders
|
|
38
|
-
import { Button } from "../../components";
|
|
39
|
-
import { useAuth } from "../../../hooks";
|
|
40
|
-
|
|
41
|
-
// ❌ Bad — deep imports into component internals
|
|
42
|
-
import { Button } from "@/components/buttons/primary-button";
|
|
43
|
-
import { useAuth } from "@/hooks/auth/useAuth";
|
|
44
|
-
import { fetchUsers } from "@/apis/users/fetchUsers";
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
**Default Allowed Folders:**
|
|
48
|
-
`actions`, `apis`, `assets`, `atoms`, `components`, `config`, `configs`, `constants`, `contexts`, `data`, `enums`, `helpers`, `hooks`, `interfaces`, `layouts`, `lib`, `middlewares`, `pages`, `providers`, `reducers`, `redux`, `requests`, `routes`, `schemas`, `services`, `store`, `styles`, `theme`, `thunks`, `types`, `ui`, `utils`, `utilities`, `views`
|
|
49
|
-
|
|
50
|
-
**Customization Options:**
|
|
51
|
-
|
|
52
|
-
| Option | Type | Description |
|
|
53
|
-
|--------|------|-------------|
|
|
54
|
-
| `extraAllowedFolders` | `string[]` | Add custom folders that can be imported with `@/folder`. Extends defaults without replacing them. Use when your project has folders like `features/`, `modules/`, etc. |
|
|
55
|
-
| `extraReduxSubfolders` | `string[]` | Add Redux-related subfolders that can be imported directly (`@/selectors`) or nested (`@/redux/selectors`). Default subfolders: `actions`, `reducers`, `store`, `thunks`, `types` |
|
|
56
|
-
| `extraDeepImportFolders` | `string[]` | Add folders where direct file imports are allowed (`@/assets/images/logo.svg`). Use for folders without index files like images, fonts, etc. Default: `assets` |
|
|
57
|
-
| `aliasPrefix` | `string` | Change the path alias prefix if your project uses something other than `@/` (e.g., `~/`, `src/`) |
|
|
58
|
-
| `allowedFolders` | `string[]` | Completely replace the default allowed folders list. Use only if you need full control over which folders are valid |
|
|
59
|
-
| `reduxSubfolders` | `string[]` | Completely replace the default Redux subfolders list |
|
|
60
|
-
| `deepImportFolders` | `string[]` | Completely replace the default deep import folders list |
|
|
61
|
-
|
|
62
|
-
```javascript
|
|
63
|
-
// Example: Add custom folders to the defaults
|
|
64
|
-
"code-style/absolute-imports-only": ["error", {
|
|
65
|
-
extraAllowedFolders: ["features", "modules"],
|
|
66
|
-
extraDeepImportFolders: ["images", "fonts"]
|
|
67
|
-
}]
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
### `export-format`
|
|
73
|
-
|
|
74
|
-
**What it does:** Formats export statements consistently:
|
|
75
|
-
- `export {` always on the same line as `export` keyword
|
|
76
|
-
- ≤3 specifiers stay on one line (collapsed)
|
|
77
|
-
- 4+ specifiers get one per line (expanded)
|
|
78
|
-
- Proper spacing and trailing commas
|
|
79
|
-
|
|
80
|
-
**Why use it:** Consistent export formatting improves readability. Short exports stay compact, long exports become scannable.
|
|
81
|
-
|
|
82
|
-
```javascript
|
|
83
|
-
// ✅ Good — 3 or fewer specifiers stay compact
|
|
84
|
-
export { Button };
|
|
85
|
-
export { Button, Input };
|
|
86
|
-
export { Button, Input, Select };
|
|
87
|
-
|
|
88
|
-
// ✅ Good — 4+ specifiers expand with one per line
|
|
89
|
-
export {
|
|
90
|
-
Button,
|
|
91
|
-
Input,
|
|
92
|
-
Select,
|
|
93
|
-
Checkbox,
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
// ✅ Good — re-exports follow same rules
|
|
97
|
-
export { Button, Input, Select } from "./components";
|
|
98
|
-
export {
|
|
99
|
-
createUser,
|
|
100
|
-
updateUser,
|
|
101
|
-
deleteUser,
|
|
102
|
-
getUser,
|
|
103
|
-
} from "./api";
|
|
104
|
-
|
|
105
|
-
// ❌ Bad — no spaces
|
|
106
|
-
export {Button,Input,Select};
|
|
107
|
-
|
|
108
|
-
// ❌ Bad — keyword on different line
|
|
109
|
-
export
|
|
110
|
-
{ Button };
|
|
111
|
-
|
|
112
|
-
// ❌ Bad — too many on one line
|
|
113
|
-
export { Button, Input, Select, Checkbox, Radio };
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
**Options:**
|
|
117
|
-
|
|
118
|
-
| Option | Type | Default | Description |
|
|
119
|
-
|--------|------|---------|-------------|
|
|
120
|
-
| `maxSpecifiers` | `integer` | `3` | Maximum specifiers to keep on single line |
|
|
121
|
-
|
|
122
|
-
```javascript
|
|
123
|
-
"code-style/export-format": ["error", { maxSpecifiers: 4 }]
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
### `import-format`
|
|
129
|
-
|
|
130
|
-
**What it does:** Formats import statements consistently:
|
|
131
|
-
- `import {` on the same line as `import` keyword
|
|
132
|
-
- `} from` on the same line as closing brace
|
|
133
|
-
- ≤3 specifiers stay on one line (collapsed)
|
|
134
|
-
- 4+ specifiers get one per line (expanded)
|
|
135
|
-
|
|
136
|
-
**Why use it:** Consistent import formatting improves readability and makes diffs cleaner when adding/removing imports.
|
|
137
|
-
|
|
138
|
-
```javascript
|
|
139
|
-
// ✅ Good — 3 or fewer specifiers stay compact
|
|
140
|
-
import { useState } from "react";
|
|
141
|
-
import { Button, Input } from "@/components";
|
|
142
|
-
import { get, post, put } from "@/api";
|
|
143
|
-
|
|
144
|
-
// ✅ Good — 4+ specifiers expand with one per line
|
|
145
|
-
import {
|
|
146
|
-
useState,
|
|
147
|
-
useEffect,
|
|
148
|
-
useCallback,
|
|
149
|
-
useMemo,
|
|
150
|
-
} from "react";
|
|
151
|
-
|
|
152
|
-
import {
|
|
153
|
-
Button,
|
|
154
|
-
Input,
|
|
155
|
-
Select,
|
|
156
|
-
Checkbox,
|
|
157
|
-
} from "@/components";
|
|
158
|
-
|
|
159
|
-
// ❌ Bad — no spaces
|
|
160
|
-
import {useState,useEffect} from "react";
|
|
161
|
-
|
|
162
|
-
// ❌ Bad — keyword on different line
|
|
163
|
-
import
|
|
164
|
-
{ Button } from "@/components";
|
|
165
|
-
|
|
166
|
-
// ❌ Bad — from on different line
|
|
167
|
-
import { Button }
|
|
168
|
-
from "@/components";
|
|
169
|
-
|
|
170
|
-
// ❌ Bad — too many on one line
|
|
171
|
-
import { useState, useEffect, useCallback, useMemo, useRef } from "react";
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
**Options:**
|
|
175
|
-
|
|
176
|
-
| Option | Type | Default | Description |
|
|
177
|
-
|--------|------|---------|-------------|
|
|
178
|
-
| `maxSpecifiers` | `integer` | `3` | Maximum specifiers to keep on single line |
|
|
179
|
-
|
|
180
|
-
```javascript
|
|
181
|
-
"code-style/import-format": ["error", { maxSpecifiers: 4 }]
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
---
|
|
185
|
-
|
|
186
|
-
### `import-source-spacing`
|
|
187
|
-
|
|
188
|
-
**What it does:** Removes any leading or trailing whitespace inside import path strings.
|
|
189
|
-
|
|
190
|
-
**Why use it:** Spaces in module paths are almost always typos and can cause import resolution issues.
|
|
191
|
-
|
|
192
|
-
```javascript
|
|
193
|
-
// ✅ Good — no extra spaces
|
|
194
|
-
import { Button } from "@mui/material";
|
|
195
|
-
import React from "react";
|
|
196
|
-
import styles from "./styles.css";
|
|
197
|
-
|
|
198
|
-
// ❌ Bad — leading space
|
|
199
|
-
import { Button } from " @mui/material";
|
|
200
|
-
|
|
201
|
-
// ❌ Bad — trailing space
|
|
202
|
-
import React from "react ";
|
|
203
|
-
|
|
204
|
-
// ❌ Bad — both
|
|
205
|
-
import styles from " ./styles.css ";
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
---
|
|
209
|
-
|
|
210
|
-
### `index-export-style`
|
|
211
|
-
|
|
212
|
-
**What it does:** Enforces different export formatting rules for index files vs regular files:
|
|
213
|
-
- **Index files**: No blank lines between exports, use shorthand or import-export style
|
|
214
|
-
- **Regular files**: Require blank lines between exports
|
|
215
|
-
|
|
216
|
-
**Why use it:** Index files are re-export aggregators and should be compact. Regular files benefit from spacing between exports for readability.
|
|
217
|
-
|
|
218
|
-
**Regular files (non-index):**
|
|
219
|
-
```javascript
|
|
220
|
-
// ✅ Good — blank lines between exports
|
|
221
|
-
export const API_URL = "/api";
|
|
222
|
-
|
|
223
|
-
export const MAX_RETRIES = 3;
|
|
224
|
-
|
|
225
|
-
export const fetchData = async () => {};
|
|
226
|
-
|
|
227
|
-
// ❌ Bad — no blank lines in regular file
|
|
228
|
-
export const API_URL = "/api";
|
|
229
|
-
export const MAX_RETRIES = 3;
|
|
230
|
-
export const fetchData = async () => {};
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
**Index files — Style: "shorthand" (default):**
|
|
234
|
-
```javascript
|
|
235
|
-
// ✅ Good — shorthand re-exports, no blank lines
|
|
236
|
-
export { Button } from "./button";
|
|
237
|
-
export { Input, Select } from "./form";
|
|
238
|
-
export { Modal } from "./modal";
|
|
239
|
-
export { useAuth, useUser } from "./hooks";
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
**Index files — Style: "import-export":**
|
|
243
|
-
```javascript
|
|
244
|
-
// ✅ Good — imports grouped, single export at bottom
|
|
245
|
-
import { Button } from "./button";
|
|
246
|
-
import { Input, Select } from "./form";
|
|
247
|
-
import { Modal } from "./modal";
|
|
248
|
-
|
|
249
|
-
export {
|
|
250
|
-
Button,
|
|
251
|
-
Input,
|
|
252
|
-
Modal,
|
|
253
|
-
Select,
|
|
254
|
-
};
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
**Options:**
|
|
258
|
-
|
|
259
|
-
| Option | Type | Default | Description |
|
|
260
|
-
|--------|------|---------|-------------|
|
|
261
|
-
| `style` | `"shorthand"` \| `"import-export"` | `"shorthand"` | Export style for index files |
|
|
262
|
-
|
|
263
|
-
```javascript
|
|
264
|
-
"code-style/index-export-style": ["error", { style: "import-export" }]
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
---
|
|
268
|
-
|
|
269
|
-
### `index-exports-only`
|
|
270
|
-
|
|
271
|
-
**What it does:** Index files (`index.ts`, `index.tsx`, `index.js`, `index.jsx`) should only contain imports and re-exports, not any code definitions. All definitions (types, interfaces, functions, variables, classes) should be moved to separate files.
|
|
272
|
-
|
|
273
|
-
**Why use it:** Index files should be "barrels" that aggregate exports from a module. Mixing definitions with re-exports makes the codebase harder to navigate and can cause circular dependency issues.
|
|
274
|
-
|
|
275
|
-
```javascript
|
|
276
|
-
// ✅ Good — index.ts with only imports and re-exports
|
|
277
|
-
export { Button } from "./Button";
|
|
278
|
-
export { helper } from "./utils";
|
|
279
|
-
export type { ButtonProps } from "./types";
|
|
280
|
-
export * from "./constants";
|
|
281
|
-
|
|
282
|
-
// ❌ Bad — index.ts with code definitions
|
|
283
|
-
export type ButtonVariant = "primary" | "secondary"; // Move to types.ts
|
|
284
|
-
export interface ButtonProps { ... } // Move to types.ts
|
|
285
|
-
export const CONSTANT = "value"; // Move to constants.ts
|
|
286
|
-
export function helper() { ... } // Move to utils.ts
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
|
|
291
|
-
### `inline-export-declaration`
|
|
292
|
-
|
|
293
|
-
**What it does:** Enforces that exports are declared inline with the declaration (`export const`, `export function`) instead of using grouped export statements (`export { ... }`). Auto-fixable: adds `export` to each declaration and removes the grouped export statement.
|
|
294
|
-
|
|
295
|
-
**Why use it:** Inline exports make it immediately clear which declarations are public. Grouped exports at the bottom of a file require scrolling to discover what's exported, and they can become stale or inconsistent with the actual declarations.
|
|
296
|
-
|
|
297
|
-
**Important exceptions:**
|
|
298
|
-
- **Index files** (barrel re-exports) are skipped entirely -- they should use grouped/re-export syntax
|
|
299
|
-
- **Aliased exports** (`export { a as b }`) are skipped since they cannot be expressed as inline exports
|
|
300
|
-
|
|
301
|
-
```javascript
|
|
302
|
-
// ✅ Good — inline export declarations
|
|
303
|
-
export const strings = {
|
|
304
|
-
title: "Hello",
|
|
305
|
-
subtitle: "World",
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
export const MAX_RETRIES = 3;
|
|
309
|
-
|
|
310
|
-
export function fetchData() {
|
|
311
|
-
return fetch("/api/data");
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// ❌ Bad — grouped export statement
|
|
315
|
-
const strings = {
|
|
316
|
-
title: "Hello",
|
|
317
|
-
subtitle: "World",
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
const MAX_RETRIES = 3;
|
|
321
|
-
|
|
322
|
-
function fetchData() {
|
|
323
|
-
return fetch("/api/data");
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
export { strings, MAX_RETRIES, fetchData };
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
---
|
|
330
|
-
|
|
331
|
-
### `module-index-exports`
|
|
332
|
-
|
|
333
|
-
**What it does:** Ensures module folders have index files that export all their contents, creating a proper public API for each module.
|
|
334
|
-
|
|
335
|
-
**Why use it:** Index files allow importing from the folder level (`@/components`) instead of deep paths (`@/components/Button/Button`). This enforces proper module boundaries.
|
|
336
|
-
|
|
337
|
-
```javascript
|
|
338
|
-
// ✅ Good — components/index.js exports everything
|
|
339
|
-
export { Button } from "./Button";
|
|
340
|
-
export { Input } from "./Input";
|
|
341
|
-
export { Select } from "./Select";
|
|
342
|
-
export { Modal } from "./Modal";
|
|
343
|
-
|
|
344
|
-
// Then consumers can import cleanly:
|
|
345
|
-
import { Button, Input, Select } from "@/components";
|
|
346
|
-
|
|
347
|
-
// ❌ Bad — missing exports in index.js
|
|
348
|
-
// If Button exists but isn't exported from index.js,
|
|
349
|
-
// consumers have to use deep imports:
|
|
350
|
-
import { Button } from "@/components/Button/Button"; // Avoid this!
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
**Default Module Folders:**
|
|
354
|
-
`actions`, `apis`, `assets`, `atoms`, `components`, `config`, `configs`, `constants`, `contexts`, `data`, `enums`, `helpers`, `hooks`, `interfaces`, `layouts`, `lib`, `middlewares`, `pages`, `providers`, `reducers`, `redux`, `requests`, `routes`, `schemas`, `services`, `store`, `styles`, `theme`, `thunks`, `types`, `ui`, `utils`, `utilities`, `views`
|
|
355
|
-
|
|
356
|
-
**Default Ignore Patterns:**
|
|
357
|
-
`index.js`, `index.jsx`, `index.ts`, `index.tsx`, `.DS_Store`, `__tests__`, `__mocks__`, `*.test.js`, `*.test.jsx`, `*.test.ts`, `*.test.tsx`, `*.spec.js`, `*.spec.jsx`, `*.spec.ts`, `*.spec.tsx`
|
|
358
|
-
|
|
359
|
-
**Customization Options:**
|
|
360
|
-
|
|
361
|
-
| Option | Type | Description |
|
|
362
|
-
|--------|------|-------------|
|
|
363
|
-
| `extraModuleFolders` | `string[]` | Add folders that should have an `index.js` re-exporting all public files. Use for project-specific folders like `features/`, `modules/` that follow the same pattern |
|
|
364
|
-
| `extraLazyLoadFolders` | `string[]` | Add folders exempt from index file requirements. Use for route/page components loaded via dynamic `import()`. Default: `pages`, `views` |
|
|
365
|
-
| `extraIgnorePatterns` | `string[]` | Add file patterns to skip when checking for index exports. Supports wildcards like `*.stories.js`, `*.mock.js` |
|
|
366
|
-
| `moduleFolders` | `string[]` | Completely replace the default module folders list. Use only if you need full control over which folders require index files |
|
|
367
|
-
| `lazyLoadFolders` | `string[]` | Completely replace the default lazy load folders list |
|
|
368
|
-
| `ignorePatterns` | `string[]` | Completely replace the default ignore patterns list |
|
|
369
|
-
|
|
370
|
-
```javascript
|
|
371
|
-
// Example: Add custom folders and patterns
|
|
372
|
-
"code-style/module-index-exports": ["error", {
|
|
373
|
-
extraModuleFolders: ["features", "modules"],
|
|
374
|
-
extraLazyLoadFolders: ["screens"],
|
|
375
|
-
extraIgnorePatterns: ["*.stories.js", "*.mock.js"]
|
|
376
|
-
}]
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
<br />
|
|
380
|
-
|
|
381
|
-
---
|
|
382
|
-
|
|
383
|
-
[← Back to Rules Index](./README.md) | [← Back to Main README](../../README.md)
|