@reasonabletech/eslint-config 0.1.0 → 0.2.1
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/CHANGELOG.md +28 -1
- package/docs/concepts/ai-code-safety.md +268 -0
- package/docs/concepts/architecture.md +394 -0
- package/docs/guides/migration.md +47 -0
- package/docs/guides/usage-guide.md +236 -0
- package/docs/index.md +29 -0
- package/docs/reference/api-reference.md +230 -0
- package/docs/reference/base-config.md +118 -0
- package/docs/reference/frameworks/README.md +61 -0
- package/docs/reference/frameworks/next-config.md +187 -0
- package/docs/reference/frameworks/react-config.md +273 -0
- package/docs/tutorials/refactoring-react-for-type-safety.md +411 -0
- package/package.json +3 -2
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Migration Guide
|
|
2
|
+
|
|
3
|
+
This guide documents breaking changes and how to migrate between major versions of @reasonabletech/eslint-config.
|
|
4
|
+
|
|
5
|
+
## Current Version
|
|
6
|
+
|
|
7
|
+
The current major version is **0.x** (pre-1.0). The API is stabilizing but may have breaking changes before 1.0.
|
|
8
|
+
|
|
9
|
+
## Future Migration Notes
|
|
10
|
+
|
|
11
|
+
_No breaking changes documented yet. This section will be updated when breaking changes are released._
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Migration Template
|
|
16
|
+
|
|
17
|
+
When documenting a breaking change, use this structure:
|
|
18
|
+
|
|
19
|
+
### Migrating from X.x to Y.0
|
|
20
|
+
|
|
21
|
+
#### Breaking Changes
|
|
22
|
+
|
|
23
|
+
1. **Change description** - Brief explanation of what changed
|
|
24
|
+
|
|
25
|
+
**Before:**
|
|
26
|
+
```typescript
|
|
27
|
+
// Old usage
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**After:**
|
|
31
|
+
```typescript
|
|
32
|
+
// New usage
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
2. **Another change** - Description
|
|
36
|
+
|
|
37
|
+
#### Deprecations
|
|
38
|
+
|
|
39
|
+
- `oldFunction()` is deprecated in favor of `newFunction()`
|
|
40
|
+
|
|
41
|
+
#### New Features
|
|
42
|
+
|
|
43
|
+
- Feature description
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
_Last updated: [date]_
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# Usage Guide
|
|
2
|
+
|
|
3
|
+
## Quick Start
|
|
4
|
+
|
|
5
|
+
### 1. Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add -D @reasonabletech/eslint-config
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### 2. Basic Setup
|
|
12
|
+
|
|
13
|
+
Create an `eslint.config.mjs` file in your project root:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
// eslint.config.mjs
|
|
17
|
+
import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
18
|
+
|
|
19
|
+
export default createTypeAwareConfig(import.meta.dirname);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 3. Add Scripts
|
|
23
|
+
|
|
24
|
+
Update your `package.json`:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"scripts": {
|
|
29
|
+
"lint": "eslint . --fix",
|
|
30
|
+
"lint:check": "eslint ."
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 4. Verify Setup
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pnpm lint
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Framework-Specific Configurations
|
|
42
|
+
|
|
43
|
+
### React Projects
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// eslint.config.mjs
|
|
47
|
+
import { createTypeAwareReactConfig } from "@reasonabletech/eslint-config/react";
|
|
48
|
+
|
|
49
|
+
export default createTypeAwareReactConfig(import.meta.dirname);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Adds React Hooks rules, JSX transform support, browser globals, and relaxed parameter typing for component props.
|
|
53
|
+
|
|
54
|
+
### Next.js Applications
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// eslint.config.mjs
|
|
58
|
+
import { createTypeAwareNextConfig } from "@reasonabletech/eslint-config/next";
|
|
59
|
+
|
|
60
|
+
export default createTypeAwareNextConfig(import.meta.dirname);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Adds Next.js Core Web Vitals rules, server action support (async without explicit `await`), and Next.js-specific ignores.
|
|
64
|
+
|
|
65
|
+
## Custom Rule Overrides
|
|
66
|
+
|
|
67
|
+
Spread the config and add overrides after it:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// eslint.config.mjs
|
|
71
|
+
import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
72
|
+
|
|
73
|
+
export default [
|
|
74
|
+
...createTypeAwareConfig(import.meta.dirname),
|
|
75
|
+
{
|
|
76
|
+
rules: {
|
|
77
|
+
"@typescript-eslint/no-unused-vars": "warn",
|
|
78
|
+
"prefer-const": "error",
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### File-Specific Overrides
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// eslint.config.mjs
|
|
88
|
+
import { createTypeAwareReactConfig } from "@reasonabletech/eslint-config/react";
|
|
89
|
+
|
|
90
|
+
export default [
|
|
91
|
+
...createTypeAwareReactConfig(import.meta.dirname),
|
|
92
|
+
{
|
|
93
|
+
files: ["**/*.test.tsx"],
|
|
94
|
+
rules: {
|
|
95
|
+
"@typescript-eslint/no-non-null-assertion": "off",
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Monorepo Usage
|
|
102
|
+
|
|
103
|
+
### Package-Specific Configurations
|
|
104
|
+
|
|
105
|
+
Each package can have its own `eslint.config.mjs`:
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// packages/my-package/eslint.config.mjs
|
|
109
|
+
import { createTypeAwareReactConfig } from "@reasonabletech/eslint-config/react";
|
|
110
|
+
|
|
111
|
+
export default createTypeAwareReactConfig(import.meta.dirname);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Workspace Root Configuration
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// eslint.config.mjs (root)
|
|
118
|
+
import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
119
|
+
|
|
120
|
+
export default createTypeAwareConfig(import.meta.dirname);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Ignored Files & Patterns
|
|
124
|
+
|
|
125
|
+
The configuration automatically ignores files that would cause TypeScript project conflicts or are not worth linting.
|
|
126
|
+
|
|
127
|
+
### Automatically Ignored Categories
|
|
128
|
+
|
|
129
|
+
- **Build outputs** — `dist/`, `build/`, `.next/`, `out/`, `coverage/`
|
|
130
|
+
- **Dependencies** — `node_modules/`
|
|
131
|
+
- **Generated files** — `*.d.ts`, `*.generated.*`, `generated/`
|
|
132
|
+
- **Config files** — `*.config.*`, `tsconfig*.json`, `package*.json` (prevents "file not in tsconfig" errors)
|
|
133
|
+
- **IDE/cache** — `.vscode/`, `.idea/`, `.turbo/`, `.cache/`
|
|
134
|
+
- **Lock files** — `pnpm-lock.yaml`, `yarn.lock`
|
|
135
|
+
- **Examples** — `examples/`
|
|
136
|
+
|
|
137
|
+
### Adding Custom Ignores
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// eslint.config.mjs
|
|
141
|
+
import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
142
|
+
|
|
143
|
+
export default [
|
|
144
|
+
...createTypeAwareConfig(import.meta.dirname),
|
|
145
|
+
{
|
|
146
|
+
ignores: ["archived-code/**", "*.special.js"],
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Integration with Development Tools
|
|
152
|
+
|
|
153
|
+
### VS Code
|
|
154
|
+
|
|
155
|
+
Create `.vscode/settings.json`:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"editor.codeActionsOnSave": {
|
|
160
|
+
"source.fixAll.eslint": "explicit"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Pre-commit Hooks
|
|
166
|
+
|
|
167
|
+
Using lint-staged:
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"lint-staged": {
|
|
172
|
+
"*.{ts,tsx,js,jsx}": ["eslint --fix"]
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### CI/CD
|
|
178
|
+
|
|
179
|
+
```yaml
|
|
180
|
+
- run: pnpm lint:check
|
|
181
|
+
- run: pnpm typecheck
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Troubleshooting
|
|
185
|
+
|
|
186
|
+
### "Parsing error: Cannot read file 'tsconfig.json'"
|
|
187
|
+
|
|
188
|
+
Your `tsconfig.json` must be in the project directory passed to the config function:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
npx tsc --showConfig
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### "Rule requires type checking to be enabled"
|
|
195
|
+
|
|
196
|
+
Make sure you're using a `createTypeAware*` function, not manually constructing config:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
// Correct
|
|
200
|
+
export default createTypeAwareConfig(import.meta.dirname);
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### "Cannot resolve module" errors
|
|
204
|
+
|
|
205
|
+
Verify the package is installed:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
pnpm list @reasonabletech/eslint-config
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Performance on Large Projects
|
|
212
|
+
|
|
213
|
+
Type-aware linting is slower than syntax-only linting. For large projects:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
# Use ESLint cache
|
|
217
|
+
pnpm eslint . --cache
|
|
218
|
+
|
|
219
|
+
# Increase memory if needed
|
|
220
|
+
NODE_OPTIONS="--max-old-space-size=4096" pnpm lint
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Debugging Configuration
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# See which rules are active for a file
|
|
227
|
+
npx eslint --print-config src/index.ts
|
|
228
|
+
|
|
229
|
+
# Check if a specific file is ignored
|
|
230
|
+
npx eslint path/to/file.ts --debug
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Related Documentation
|
|
234
|
+
|
|
235
|
+
- [API Reference](../reference/api-reference.md) — All exported functions and plugin rules
|
|
236
|
+
- [Architecture](../concepts/architecture.md) — Design decisions and internal structure
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @reasonabletech/eslint-config Documentation
|
|
2
|
+
|
|
3
|
+
For quick setup, see the [README](../README.md).
|
|
4
|
+
|
|
5
|
+
## Guides
|
|
6
|
+
|
|
7
|
+
- **[Usage Guide](./guides/usage-guide.md)** — Setup instructions, custom overrides, monorepo patterns, troubleshooting, and ignored file patterns
|
|
8
|
+
|
|
9
|
+
## Reference
|
|
10
|
+
|
|
11
|
+
- **[API Reference](./reference/api-reference.md)** — All exported functions, the `@reasonabletech` plugin, and custom rule documentation
|
|
12
|
+
- **[Base Configuration](./reference/base-config.md)** — Core configuration specifications and rule details
|
|
13
|
+
- **[Framework Configurations](./reference/frameworks/)** — React and Next.js specific configuration details
|
|
14
|
+
|
|
15
|
+
## Concepts
|
|
16
|
+
|
|
17
|
+
- **[Architecture](./concepts/architecture.md)** — Design principles, configuration composition, and internal structure
|
|
18
|
+
- **[AI Code Safety](./concepts/ai-code-safety.md)** — Why strict type-aware linting matters for AI-generated code
|
|
19
|
+
|
|
20
|
+
## Tutorials
|
|
21
|
+
|
|
22
|
+
- **[Refactoring React for Type Safety](./tutorials/refactoring-react-for-type-safety.md)** — Fixing `strict-boolean-expressions` violations in React components
|
|
23
|
+
|
|
24
|
+
## Monorepo Context
|
|
25
|
+
|
|
26
|
+
- [Package README](../README.md)
|
|
27
|
+
- [Architecture](../../../docs/architecture.md) — How packages relate
|
|
28
|
+
- [Tooling](../../../docs/tooling.md) — Turbo, Changesets, ESLint details
|
|
29
|
+
- [Contributing](../../../CONTRIBUTING.md)
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
## Package Exports
|
|
4
|
+
|
|
5
|
+
The package exposes three entry points. All internal modules (`base-configs`, `shared-rules`, `shared-ignores`, etc.) are **not** part of the public API.
|
|
6
|
+
|
|
7
|
+
### `@reasonabletech/eslint-config`
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
#### `createTypeAwareConfig(projectDir: string): Linter.Config[]`
|
|
14
|
+
|
|
15
|
+
Creates a comprehensive type-aware ESLint configuration for TypeScript projects.
|
|
16
|
+
|
|
17
|
+
**Parameters:**
|
|
18
|
+
|
|
19
|
+
- `projectDir` — Absolute path to the project root (use `import.meta.dirname`)
|
|
20
|
+
|
|
21
|
+
**Returns:** Array of ESLint flat config objects
|
|
22
|
+
|
|
23
|
+
**Includes:**
|
|
24
|
+
|
|
25
|
+
- ESLint recommended rules
|
|
26
|
+
- TypeScript-ESLint recommended + type-checked rules
|
|
27
|
+
- Prettier compatibility
|
|
28
|
+
- JSDoc enforcement
|
|
29
|
+
- Turbo monorepo rules
|
|
30
|
+
- `@reasonabletech` custom plugin rules (see below)
|
|
31
|
+
- Comprehensive ignore patterns
|
|
32
|
+
- Test file relaxation (`tests/**`, `examples/**`)
|
|
33
|
+
|
|
34
|
+
**Also exports:** `sharedReactComponentRules` (shared React rules for use in custom configurations)
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
### `@reasonabletech/eslint-config/react`
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { createTypeAwareReactConfig } from "@reasonabletech/eslint-config/react";
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### `createTypeAwareReactConfig(projectDir: string): Linter.Config[]`
|
|
45
|
+
|
|
46
|
+
Creates a type-aware ESLint configuration for React projects.
|
|
47
|
+
|
|
48
|
+
**Parameters:**
|
|
49
|
+
|
|
50
|
+
- `projectDir` — Absolute path to the project root
|
|
51
|
+
|
|
52
|
+
**Includes everything in the base config plus:**
|
|
53
|
+
|
|
54
|
+
- React Hooks plugin (`rules-of-hooks`, `exhaustive-deps`)
|
|
55
|
+
- React Refresh plugin for HMR
|
|
56
|
+
- JSX transform compatibility (no React import required)
|
|
57
|
+
- Browser and service worker globals
|
|
58
|
+
- Relaxed parameter typing for component props
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
### `@reasonabletech/eslint-config/next`
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { createTypeAwareNextConfig } from "@reasonabletech/eslint-config/next";
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### `createTypeAwareNextConfig(projectDir: string): Linter.Config[]`
|
|
69
|
+
|
|
70
|
+
Creates a type-aware ESLint configuration for Next.js applications.
|
|
71
|
+
|
|
72
|
+
**Parameters:**
|
|
73
|
+
|
|
74
|
+
- `projectDir` — Absolute path to the project root
|
|
75
|
+
|
|
76
|
+
**Includes everything in the React config plus:**
|
|
77
|
+
|
|
78
|
+
- Next.js Core Web Vitals rules
|
|
79
|
+
- Server action support (async functions without explicit `await`)
|
|
80
|
+
- Next.js-specific ignore patterns (`.next/`, `out/`)
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## `@reasonabletech` ESLint Plugin
|
|
85
|
+
|
|
86
|
+
All configurations automatically register the `@reasonabletech` ESLint plugin, which provides 4 custom rules implemented with `ESLintUtils.RuleCreator`:
|
|
87
|
+
|
|
88
|
+
### `@reasonabletech/no-dependency-bundling`
|
|
89
|
+
|
|
90
|
+
Prevents dependency "god object" patterns where multiple services are bundled into a single `Dependencies` object.
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// Triggers lint error
|
|
94
|
+
class UserService {
|
|
95
|
+
constructor(private deps: Dependencies) {} // "Dependencies" suffix detected
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Correct: inject dependencies individually
|
|
99
|
+
class UserService {
|
|
100
|
+
constructor(
|
|
101
|
+
private db: DatabaseClient,
|
|
102
|
+
private logger: Logger,
|
|
103
|
+
) {}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### `@reasonabletech/no-linter-disabling`
|
|
108
|
+
|
|
109
|
+
Requires justification comments when disabling ESLint rules. Bare `eslint-disable` comments without explanation are flagged.
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// Triggers lint error
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
114
|
+
|
|
115
|
+
// Correct: provide justification
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- Required by framework callback signature
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### `@reasonabletech/no-null-undefined-checks`
|
|
120
|
+
|
|
121
|
+
Catches null/undefined checks that don't match the variable's declared type union. For example, checking `=== null` when the type is `T | undefined` (not `T | null`).
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
function process(value: string | undefined) {
|
|
125
|
+
// Triggers lint error: null is not in the type union
|
|
126
|
+
if (value === null) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Correct: check for what's actually in the type
|
|
131
|
+
if (value === undefined) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### `@reasonabletech/use-result-helpers`
|
|
138
|
+
|
|
139
|
+
Enforces use of `ok()` and `err()` helper functions from `@reasonabletech/utils` instead of manually constructing Result objects.
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// Triggers lint error
|
|
143
|
+
return { success: true, data: user };
|
|
144
|
+
|
|
145
|
+
// Correct: use helpers
|
|
146
|
+
return ok(user);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Additional Rule Enforcement
|
|
152
|
+
|
|
153
|
+
Beyond the 4 plugin rules, configurations also enforce patterns via `no-restricted-syntax` AST selectors. These are organized as factory functions in `src/custom-rules/`:
|
|
154
|
+
|
|
155
|
+
| Factory Function | What It Enforces |
|
|
156
|
+
| ---------------------------------- | -------------------------------------------------------------------- |
|
|
157
|
+
| `createErrorHandlingRules()` | No error message parsing, documented error types, naming conventions |
|
|
158
|
+
| `createTypeSafetyRules()` | No `as any` casts, no double casts through `any` |
|
|
159
|
+
| `createArchitecturePatternRules()` | Service architecture patterns, DI enforcement |
|
|
160
|
+
| `createCodeQualityRules()` | No `export *` (barrel exports), no mixed async patterns |
|
|
161
|
+
| `createPlatformConventionRules()` | UI barrel import restrictions |
|
|
162
|
+
| `createNullUndefinedChecksRules()` | Additional null/undefined pattern enforcement |
|
|
163
|
+
|
|
164
|
+
### Preset Functions
|
|
165
|
+
|
|
166
|
+
Two preset functions combine these rule sets:
|
|
167
|
+
|
|
168
|
+
#### `createPlatformRulePreset(): Linter.RulesRecord`
|
|
169
|
+
|
|
170
|
+
All rules with platform-specific defaults (strict settings, platform documentation URLs).
|
|
171
|
+
|
|
172
|
+
#### `createGenericRulePreset(docBaseUrl?: string): Linter.RulesRecord`
|
|
173
|
+
|
|
174
|
+
Subset of rules suitable for non-projects. Accepts a custom documentation base URL.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Usage Patterns
|
|
179
|
+
|
|
180
|
+
### Standard project
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// eslint.config.mjs
|
|
184
|
+
import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
185
|
+
|
|
186
|
+
export default createTypeAwareConfig(import.meta.dirname);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### With custom overrides
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
// eslint.config.mjs
|
|
193
|
+
import { createTypeAwareConfig } from "@reasonabletech/eslint-config";
|
|
194
|
+
|
|
195
|
+
export default [
|
|
196
|
+
...createTypeAwareConfig(import.meta.dirname),
|
|
197
|
+
{
|
|
198
|
+
rules: {
|
|
199
|
+
"@typescript-eslint/no-unused-vars": "warn",
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
];
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### File-specific overrides
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
// eslint.config.mjs
|
|
209
|
+
import { createTypeAwareReactConfig } from "@reasonabletech/eslint-config/react";
|
|
210
|
+
|
|
211
|
+
export default [
|
|
212
|
+
...createTypeAwareReactConfig(import.meta.dirname),
|
|
213
|
+
{
|
|
214
|
+
files: ["**/*.test.tsx"],
|
|
215
|
+
rules: {
|
|
216
|
+
"@typescript-eslint/no-non-null-assertion": "off",
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
];
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## TypeScript Integration
|
|
223
|
+
|
|
224
|
+
All configurations use `projectService: true` for automatic `tsconfig.json` discovery. Your project must have a valid `tsconfig.json` in the project root.
|
|
225
|
+
|
|
226
|
+
## Related Documentation
|
|
227
|
+
|
|
228
|
+
- [Usage Guide](../guides/usage-guide.md) — Setup and troubleshooting
|
|
229
|
+
- [Architecture](../concepts/architecture.md) — Design decisions
|
|
230
|
+
- [Custom Rules README](../../src/custom-rules/README.md) — Rule implementation details and contributing guide
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Base ESLint Configuration
|
|
2
|
+
|
|
3
|
+
The base configuration (`@reasonabletech/eslint-config`) provides fundamental linting rules suitable for all TypeScript projects in the monorepo.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ESLint recommended rules for code quality
|
|
8
|
+
- Prettier integration to avoid conflicts with code formatting
|
|
9
|
+
- TypeScript-ESLint recommended rules for type safety
|
|
10
|
+
- Turbo rules for monorepo health
|
|
11
|
+
- Error handling best practices
|
|
12
|
+
- Consistent type annotations
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
This package is installed as a workspace dependency:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add -D @reasonabletech/eslint-config
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
Create an `eslint.config.js` file in your project root:
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
// eslint.config.js
|
|
28
|
+
import { config } from "@reasonabletech/eslint-config";
|
|
29
|
+
|
|
30
|
+
export default config;
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Configuration Details
|
|
34
|
+
|
|
35
|
+
The base configuration includes:
|
|
36
|
+
|
|
37
|
+
### Core Rules
|
|
38
|
+
|
|
39
|
+
- ESLint recommended rules from `@eslint/js`
|
|
40
|
+
- Prettier compatibility via `eslint-config-prettier`
|
|
41
|
+
- TypeScript-ESLint recommended rules
|
|
42
|
+
|
|
43
|
+
### Plugins
|
|
44
|
+
|
|
45
|
+
- `turbo` - Enforces monorepo best practices
|
|
46
|
+
|
|
47
|
+
### Key Rules
|
|
48
|
+
|
|
49
|
+
- `turbo/no-undeclared-env-vars`: Errors when using undeclared environment variables
|
|
50
|
+
- `no-throw-literal`: Enforces throwing Error objects instead of literals
|
|
51
|
+
- `prefer-promise-reject-errors`: Ensures consistent error handling in Promises
|
|
52
|
+
- `no-new-native-nonconstructor`: Prevents using the global Error constructor directly
|
|
53
|
+
- `@typescript-eslint/explicit-function-return-type`: Enforces return types on functions
|
|
54
|
+
|
|
55
|
+
### Ignored Patterns
|
|
56
|
+
|
|
57
|
+
- `dist/**` - Ignores build output
|
|
58
|
+
- `scripts/**` - Ignores script files
|
|
59
|
+
- `**/scripts/**` - Ignores nested script directories
|
|
60
|
+
|
|
61
|
+
## Philosophy: Warnings as Errors
|
|
62
|
+
|
|
63
|
+
### Design Decision
|
|
64
|
+
|
|
65
|
+
All ESLint warnings are treated as errors in the the codebase. This design choice reflects our commitment to code quality and developer experience.
|
|
66
|
+
|
|
67
|
+
### Rationale
|
|
68
|
+
|
|
69
|
+
- **Fail Fast**: Issues are caught immediately rather than accumulating
|
|
70
|
+
- **CI/CD Reliability**: Builds fail on any code quality issues, preventing problematic code from reaching production
|
|
71
|
+
- **Developer Discipline**: Encourages addressing issues immediately rather than deferring them
|
|
72
|
+
- **Consistent Standards**: No distinction between "minor" and "major" issues - all violations block progress
|
|
73
|
+
- **Agentic Code Quality**: Forces AI coding tools to write higher quality code by preventing warning tolerance
|
|
74
|
+
|
|
75
|
+
### Implementation
|
|
76
|
+
|
|
77
|
+
- Removed `eslint-plugin-only-warn` that converted errors to warnings
|
|
78
|
+
- Updated rule configurations from `"warn"` to `"error"` severity
|
|
79
|
+
- All ESLint violations now cause build failures in CI/CD
|
|
80
|
+
|
|
81
|
+
### Benefits
|
|
82
|
+
|
|
83
|
+
1. **Improved Code Quality**: No ignored warnings that could lead to bugs
|
|
84
|
+
2. **Cleaner Codebase**: Zero tolerance for code quality violations
|
|
85
|
+
3. **Better Developer Habits**: Immediate feedback loop encourages best practices
|
|
86
|
+
4. **Predictable Builds**: CI failures are deterministic and actionable
|
|
87
|
+
5. **Enhanced AI Development**: Agentic coding tools are compelled to generate cleaner, more maintainable code
|
|
88
|
+
|
|
89
|
+
## Example
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
// eslint.config.js
|
|
93
|
+
import { config as baseConfig } from "@reasonabletech/eslint-config";
|
|
94
|
+
|
|
95
|
+
export default [
|
|
96
|
+
...baseConfig,
|
|
97
|
+
{
|
|
98
|
+
// Project-specific rules
|
|
99
|
+
rules: {
|
|
100
|
+
"no-console": ["warn", { allow: ["warn", "error"] }],
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
// File-specific rules
|
|
105
|
+
files: ["**/*.test.ts"],
|
|
106
|
+
rules: {
|
|
107
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Related Documentation
|
|
114
|
+
|
|
115
|
+
- [API Reference](./api-reference.md) — Complete function documentation
|
|
116
|
+
- [Framework Configurations](./frameworks/) — React and Next.js specific configurations
|
|
117
|
+
- [Usage Guide](../guides/usage-guide.md) — Setup instructions and troubleshooting
|
|
118
|
+
- [Architecture](../concepts/architecture.md) — Design principles and decisions
|