@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.
@@ -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