@etchteam/eslint-config 2.2.201 → 2.6.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/AGENTS.md +154 -0
- package/CHANGELOG.md +3 -5
- package/CLAUDE.md +1 -0
- package/README.md +98 -4
- package/package.json +35 -13
- package/src/base.mjs +70 -0
- package/src/configs/environments/angular.mjs +53 -0
- package/src/configs/environments/nestjs.mjs +31 -0
- package/src/configs/environments/nextjs.mjs +40 -0
- package/src/configs/environments/nodejs.mjs +27 -0
- package/src/configs/environments/preact.mjs +35 -0
- package/src/configs/environments/web-components.mjs +24 -0
- package/src/configs/json.mjs +11 -0
- package/src/configs/react.mjs +42 -0
- package/src/configs/storybook.mjs +6 -0
- package/src/configs/yaml.mjs +6 -0
- package/src/index.mjs +34 -99
- package/src/types.d.ts +72 -0
- package/src/utils/fixup.mjs +21 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to AI Agents when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
This is `@etchteam/eslint-config`, a shareable ESLint configuration package used by [Etch](https://etch.co). It provides modular, composable ESLint configurations for JavaScript, TypeScript, React, Angular, Next.js, Preact, Web Components, Node.js, and NestJS projects using ESLint 9's flat config format.
|
|
8
|
+
|
|
9
|
+
## Development Commands
|
|
10
|
+
|
|
11
|
+
### Linting
|
|
12
|
+
```bash
|
|
13
|
+
# Lint the source code
|
|
14
|
+
npx eslint src
|
|
15
|
+
|
|
16
|
+
# Lint with auto-fix
|
|
17
|
+
npx eslint src --fix
|
|
18
|
+
|
|
19
|
+
# Test the config against test files (should produce errors)
|
|
20
|
+
npx eslint test-files/
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Release
|
|
24
|
+
```bash
|
|
25
|
+
# Create a new release (runs semantic-release)
|
|
26
|
+
npm run release
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Note: There are no unit tests in this project. Testing is done by running ESLint against the `test-files/` directory, which should intentionally produce linting errors to verify the config rules work.
|
|
30
|
+
|
|
31
|
+
## Architecture
|
|
32
|
+
|
|
33
|
+
### Modular Config Structure
|
|
34
|
+
|
|
35
|
+
The configuration is split into composable modules:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
src/
|
|
39
|
+
├── index.mjs # Default export (full config) + named exports
|
|
40
|
+
├── base.mjs # Core: JS, TS, security, imports, prettier
|
|
41
|
+
├── configs/
|
|
42
|
+
│ ├── json.mjs # JSON file linting
|
|
43
|
+
│ ├── yaml.mjs # YAML file linting
|
|
44
|
+
│ ├── storybook.mjs # Storybook linting
|
|
45
|
+
│ ├── react.mjs # React + jsx-a11y
|
|
46
|
+
│ └── environments/
|
|
47
|
+
│ ├── nextjs.mjs # Next.js (base + react + Next.js rules)
|
|
48
|
+
│ ├── nodejs.mjs # Node.js (base, no React)
|
|
49
|
+
│ ├── angular.mjs # Angular (base + angular-eslint)
|
|
50
|
+
│ ├── preact.mjs # Preact (base + react modified)
|
|
51
|
+
│ ├── web-components.mjs # Lit/Web Components
|
|
52
|
+
│ └── nestjs.mjs # NestJS (base + nestjs rules)
|
|
53
|
+
├── utils/
|
|
54
|
+
│ └── fixup.mjs # Shared fixupPluginRules helper
|
|
55
|
+
└── types.d.ts # TypeScript definitions
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Config Composition
|
|
59
|
+
|
|
60
|
+
**Default export** (`src/index.mjs`): Backwards-compatible full config = `base + json + yaml + storybook + react`
|
|
61
|
+
|
|
62
|
+
**Named exports** for composition:
|
|
63
|
+
- `base`, `json`, `yaml`, `storybook`, `react` - Individual modules
|
|
64
|
+
- `nodejs`, `nextjs`, `preact`, `angular`, `webComponents`, `nestjs` - Self-contained environment configs
|
|
65
|
+
|
|
66
|
+
**Package.json exports map** provides direct imports:
|
|
67
|
+
- `@etchteam/eslint-config` - Default (full config)
|
|
68
|
+
- `@etchteam/eslint-config/base` - Base only
|
|
69
|
+
- `@etchteam/eslint-config/nextjs` - Next.js environment
|
|
70
|
+
- etc.
|
|
71
|
+
|
|
72
|
+
### ESLint 9 Flat Config
|
|
73
|
+
|
|
74
|
+
This config uses ESLint 9's flat config format exclusively:
|
|
75
|
+
|
|
76
|
+
- **Compatibility layer**: `src/utils/fixup.mjs` wraps plugins that don't support flat config yet (import, jsx-a11y, you-dont-need-lodash-underscore, react)
|
|
77
|
+
- **Native flat config plugins**: unused-imports, typescript-eslint, security, yml, storybook, json
|
|
78
|
+
- **Parser configuration**: TypeScript ESLint parser in `languageOptions`
|
|
79
|
+
|
|
80
|
+
### Dependencies
|
|
81
|
+
|
|
82
|
+
**Core dependencies** (always installed):
|
|
83
|
+
- `@eslint/compat`, `@eslint/js`, `typescript-eslint`
|
|
84
|
+
- `eslint-plugin-security`, `eslint-plugin-import`, `eslint-plugin-unused-imports`
|
|
85
|
+
- `eslint-plugin-prettier`, `eslint-config-prettier`
|
|
86
|
+
- `eslint-plugin-json`, `eslint-plugin-yml`, `eslint-plugin-storybook`
|
|
87
|
+
- `eslint-import-resolver-typescript`, `globals`
|
|
88
|
+
|
|
89
|
+
**Optional dependencies** (for environment-specific configs):
|
|
90
|
+
- `eslint-plugin-react`, `eslint-plugin-jsx-a11y` - React/Preact/Next.js
|
|
91
|
+
- `@next/eslint-plugin-next`, `eslint-plugin-react-hooks` - Next.js
|
|
92
|
+
- `angular-eslint` - Angular
|
|
93
|
+
- `eslint-plugin-lit` - Web Components
|
|
94
|
+
- `@darraghor/eslint-plugin-nestjs-typed` - NestJS
|
|
95
|
+
|
|
96
|
+
### Key Rules
|
|
97
|
+
|
|
98
|
+
- **Unused imports**: Enforced via `eslint-plugin-unused-imports`
|
|
99
|
+
- **Import ordering**: Alphabetical with newlines between groups, `@/` paths treated as parent group
|
|
100
|
+
- **TypeScript**: `no-explicit-any` is warning (not error), unused vars are errors
|
|
101
|
+
- **React**: Forbids `<b>` and `<i>` elements, enforces read-only props, no useless fragments
|
|
102
|
+
- **Accessibility**: Includes extended jsx-a11y rules beyond the preset
|
|
103
|
+
- **Security**: Uses recommended config with `detect-object-injection` disabled
|
|
104
|
+
- **Prettier**: Single quotes enforced, integrated via `eslint-plugin-prettier`
|
|
105
|
+
|
|
106
|
+
## Git Workflow
|
|
107
|
+
|
|
108
|
+
### Commit Messages
|
|
109
|
+
|
|
110
|
+
This repo uses [Conventional Commits](https://www.conventionalcommits.org/) enforced by commitlint:
|
|
111
|
+
- Format: `type(scope): description`
|
|
112
|
+
- Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
|
|
113
|
+
- Validated by husky pre-commit hook running commitlint
|
|
114
|
+
|
|
115
|
+
### Semantic Release
|
|
116
|
+
|
|
117
|
+
- Automatic versioning and publishing via semantic-release
|
|
118
|
+
- Runs on push to `main` branch via `.github/workflows/publish.yml`
|
|
119
|
+
- Release configuration in `release.config.js`
|
|
120
|
+
- Generates CHANGELOG.md automatically
|
|
121
|
+
- Publishes to npm with provenance
|
|
122
|
+
|
|
123
|
+
### Git Hooks
|
|
124
|
+
|
|
125
|
+
Husky hooks are configured in `.husky/`:
|
|
126
|
+
- **pre-commit**: Runs `lint-staged` which executes `eslint --fix` on staged files matching `*.{ts,tsx,js,jsx,yml,yaml,json}`
|
|
127
|
+
- **commit-msg**: Validates commit messages with commitlint
|
|
128
|
+
|
|
129
|
+
Note: `HUSKY=0` environment variable disables hooks in CI.
|
|
130
|
+
|
|
131
|
+
## CI/CD
|
|
132
|
+
|
|
133
|
+
### CI Pipeline (`.github/workflows/ci.yml`)
|
|
134
|
+
- Runs on pull requests
|
|
135
|
+
- Tests against Node.js 18, 20, 22
|
|
136
|
+
- Lints source code with `npx eslint src`
|
|
137
|
+
- Validates config against `test-files/` (expects violations to prove rules work)
|
|
138
|
+
|
|
139
|
+
### Publish Pipeline (`.github/workflows/publish.yml`)
|
|
140
|
+
- Runs on push to `main`
|
|
141
|
+
- Uses semantic-release to determine version, generate changelog, and publish
|
|
142
|
+
- Requires `NPM_TOKEN` secret for publishing
|
|
143
|
+
|
|
144
|
+
## Test Strategy
|
|
145
|
+
|
|
146
|
+
This package uses a unique testing approach:
|
|
147
|
+
- `test-files/` directory contains intentionally badly-formatted code
|
|
148
|
+
- CI runs ESLint against these files and expects failures
|
|
149
|
+
- If ESLint passes on test files, the CI fails (proves rules aren't working)
|
|
150
|
+
- This validates that the config actually enforces the expected rules
|
|
151
|
+
|
|
152
|
+
## Mergify Configuration
|
|
153
|
+
|
|
154
|
+
Auto-merge is configured in `.github/mergify.yml` for Dependabot PRs that pass CI.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
##
|
|
1
|
+
## <small>2.6.1 (2026-01-29)</small>
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* bump @typescript-eslint/parser from 8.51.0 to 8.52.0 ([5810ff2](https://github.com/etchteam/eslint/commit/5810ff2f6bbdabe90146ed0d46feafa6d0273679))
|
|
3
|
+
* Merge pull request #452 from etchteam/dependabot/npm_and_yarn/angular-eslint-21.1.0 ([67ef4e4](https://github.com/etchteam/eslint/commit/67ef4e4)), closes [#452](https://github.com/etchteam/eslint/issues/452)
|
|
4
|
+
* fix: bump angular-eslint from 19.8.1 to 21.1.0 ([b35e7c4](https://github.com/etchteam/eslint/commit/b35e7c4))
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
package/README.md
CHANGED
|
@@ -20,9 +20,103 @@ import etchConfig from '@etchteam/eslint-config';
|
|
|
20
20
|
export default etchConfig;
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
## Environment-Specific Configs
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
For projects that don't need the full config, use environment-specific imports to reduce dependencies:
|
|
26
|
+
|
|
27
|
+
### Next.js
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
import nextjs from '@etchteam/eslint-config/nextjs';
|
|
31
|
+
|
|
32
|
+
export default nextjs;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Node.js / Express
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
import nodejs from '@etchteam/eslint-config/nodejs';
|
|
39
|
+
|
|
40
|
+
export default nodejs;
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Angular
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
import angular from '@etchteam/eslint-config/angular';
|
|
47
|
+
|
|
48
|
+
export default angular;
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Preact
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
import preact from '@etchteam/eslint-config/preact';
|
|
55
|
+
|
|
56
|
+
export default preact;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Web Components (Lit)
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
import webComponents from '@etchteam/eslint-config/web-components';
|
|
63
|
+
|
|
64
|
+
export default webComponents;
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### NestJS
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
import nestjs from '@etchteam/eslint-config/nestjs';
|
|
71
|
+
|
|
72
|
+
export default nestjs;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Composable Configs
|
|
76
|
+
|
|
77
|
+
Build custom configs by combining individual modules:
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
import { base, json, yaml, react } from '@etchteam/eslint-config';
|
|
81
|
+
|
|
82
|
+
export default [
|
|
83
|
+
...base,
|
|
84
|
+
...json,
|
|
85
|
+
...yaml,
|
|
86
|
+
...react,
|
|
87
|
+
{
|
|
88
|
+
// Your custom overrides
|
|
89
|
+
rules: {
|
|
90
|
+
'react/prefer-read-only-props': 'warn',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Available Modules
|
|
97
|
+
|
|
98
|
+
| Module | Description |
|
|
99
|
+
|--------|-------------|
|
|
100
|
+
| `base` | Core rules: JS, TypeScript, security, imports, prettier |
|
|
101
|
+
| `json` | JSON file linting |
|
|
102
|
+
| `yaml` | YAML file linting |
|
|
103
|
+
| `storybook` | Storybook best practices |
|
|
104
|
+
| `react` | React + JSX accessibility |
|
|
105
|
+
|
|
106
|
+
### Environment Configs (Self-Contained)
|
|
107
|
+
|
|
108
|
+
| Config | Includes |
|
|
109
|
+
|--------|----------|
|
|
110
|
+
| `nextjs` | base + json + yaml + storybook + react + Next.js rules |
|
|
111
|
+
| `nodejs` | base + json + yaml + Node.js globals |
|
|
112
|
+
| `angular` | base + json + yaml + storybook + Angular rules |
|
|
113
|
+
| `preact` | base + json + yaml + storybook + react (Preact settings) |
|
|
114
|
+
| `web-components` | base + json + yaml + storybook + Lit rules |
|
|
115
|
+
| `nestjs` | base + json + yaml + NestJS rules + Jest globals |
|
|
116
|
+
|
|
117
|
+
## With lint-staged
|
|
118
|
+
|
|
119
|
+
### New project
|
|
26
120
|
|
|
27
121
|
Run the following:
|
|
28
122
|
|
|
@@ -37,7 +131,7 @@ echo "npx --no-install -- lint-staged" > .husky/pre-commit
|
|
|
37
131
|
|
|
38
132
|
```
|
|
39
133
|
|
|
40
|
-
|
|
134
|
+
### Existing project with husky and lint staged
|
|
41
135
|
|
|
42
136
|
Add the following to your lint-staged config:
|
|
43
137
|
|
|
@@ -108,4 +202,4 @@ ESLint 9 uses flat config by default, so your existing npm scripts should work w
|
|
|
108
202
|
- **Flat config format** - More explicit and performant
|
|
109
203
|
- **ESLint 9 compatibility** - Latest features and fixes
|
|
110
204
|
- **Updated plugins** - All plugins updated to latest versions
|
|
111
|
-
- **
|
|
205
|
+
- **Modular configs** - Import only what you need for your environment
|
package/package.json
CHANGED
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etchteam/eslint-config",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"description": "Etch's standard eslint config",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.mjs",
|
|
7
7
|
"exports": {
|
|
8
|
-
".": "./src/index.mjs"
|
|
8
|
+
".": "./src/index.mjs",
|
|
9
|
+
"./base": "./src/base.mjs",
|
|
10
|
+
"./json": "./src/configs/json.mjs",
|
|
11
|
+
"./yaml": "./src/configs/yaml.mjs",
|
|
12
|
+
"./storybook": "./src/configs/storybook.mjs",
|
|
13
|
+
"./react": "./src/configs/react.mjs",
|
|
14
|
+
"./nodejs": "./src/configs/environments/nodejs.mjs",
|
|
15
|
+
"./nextjs": "./src/configs/environments/nextjs.mjs",
|
|
16
|
+
"./preact": "./src/configs/environments/preact.mjs",
|
|
17
|
+
"./angular": "./src/configs/environments/angular.mjs",
|
|
18
|
+
"./web-components": "./src/configs/environments/web-components.mjs",
|
|
19
|
+
"./nestjs": "./src/configs/environments/nestjs.mjs",
|
|
20
|
+
"./package.json": "./package.json"
|
|
9
21
|
},
|
|
10
22
|
"scripts": {
|
|
11
23
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
12
24
|
"release": "semantic-release"
|
|
13
25
|
},
|
|
14
26
|
"engines": {
|
|
15
|
-
"node": "^
|
|
27
|
+
"node": "^20 || ^22 || ^24"
|
|
16
28
|
},
|
|
17
29
|
"repository": {
|
|
18
30
|
"type": "git",
|
|
@@ -34,28 +46,38 @@
|
|
|
34
46
|
"lint-staged": "^16.0.0"
|
|
35
47
|
},
|
|
36
48
|
"dependencies": {
|
|
37
|
-
"@eslint/compat": "^
|
|
49
|
+
"@eslint/compat": "^2.0.1",
|
|
38
50
|
"@eslint/js": "^9.29.0",
|
|
39
|
-
"@typescript-eslint/eslint-plugin": "^8.35.0",
|
|
40
|
-
"@typescript-eslint/parser": "^8.35.0",
|
|
41
|
-
"eslint": ">=9.0.0",
|
|
42
|
-
"eslint-config-next": "^16.0.0",
|
|
43
51
|
"eslint-config-prettier": "^10.1.5",
|
|
52
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
44
53
|
"eslint-plugin-import": "^2.32.0",
|
|
45
54
|
"eslint-plugin-json": "^4.0.1",
|
|
46
|
-
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
47
55
|
"eslint-plugin-prettier": "^5.5.0",
|
|
48
|
-
"eslint-plugin-react": "^7.37.5",
|
|
49
56
|
"eslint-plugin-security": "^3.0.1",
|
|
50
57
|
"eslint-plugin-storybook": "^10.0.1",
|
|
51
58
|
"eslint-plugin-unused-imports": "^4.1.3",
|
|
52
|
-
"eslint-plugin-yml": "^
|
|
59
|
+
"eslint-plugin-yml": "^3.0.0",
|
|
53
60
|
"eslint-plugin-you-dont-need-lodash-underscore": "^6.14.0",
|
|
54
|
-
"
|
|
61
|
+
"globals": "^16.0.0",
|
|
55
62
|
"typescript-eslint": "^8.35.0"
|
|
56
63
|
},
|
|
64
|
+
"optionalDependencies": {
|
|
65
|
+
"@darraghor/eslint-plugin-nestjs-typed": "^6.0.0",
|
|
66
|
+
"@next/eslint-plugin-next": "^15.0.0",
|
|
67
|
+
"angular-eslint": "^21.1.0",
|
|
68
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
69
|
+
"eslint-plugin-lit": "^1.15.0",
|
|
70
|
+
"eslint-plugin-react": "^7.37.5",
|
|
71
|
+
"eslint-plugin-react-hooks": "^5.0.0"
|
|
72
|
+
},
|
|
57
73
|
"peerDependencies": {
|
|
58
74
|
"eslint": ">=9.0.0",
|
|
59
|
-
"prettier": ">=3.0.0"
|
|
75
|
+
"prettier": ">=3.0.0",
|
|
76
|
+
"typescript": ">=4.8.4"
|
|
77
|
+
},
|
|
78
|
+
"peerDependenciesMeta": {
|
|
79
|
+
"typescript": {
|
|
80
|
+
"optional": true
|
|
81
|
+
}
|
|
60
82
|
}
|
|
61
83
|
}
|
package/src/base.mjs
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import js from '@eslint/js';
|
|
2
|
+
import importPlugin from 'eslint-plugin-import';
|
|
3
|
+
import prettier from 'eslint-plugin-prettier/recommended';
|
|
4
|
+
import security from 'eslint-plugin-security';
|
|
5
|
+
import unusedImports from 'eslint-plugin-unused-imports';
|
|
6
|
+
import youDontNeedLodash from 'eslint-plugin-you-dont-need-lodash-underscore';
|
|
7
|
+
import tseslint from 'typescript-eslint';
|
|
8
|
+
|
|
9
|
+
import { fixupPluginRules } from './utils/fixup.mjs';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Base ESLint configuration for all projects.
|
|
13
|
+
* Includes: JavaScript, TypeScript, security, import ordering, prettier, and common rules.
|
|
14
|
+
* Does NOT include: React, JSX accessibility, JSON, YAML, or Storybook configs.
|
|
15
|
+
*/
|
|
16
|
+
export default [
|
|
17
|
+
js.configs.recommended,
|
|
18
|
+
...tseslint.configs.recommended,
|
|
19
|
+
security.configs.recommended,
|
|
20
|
+
{
|
|
21
|
+
files: ['**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}'],
|
|
22
|
+
plugins: {
|
|
23
|
+
'unused-imports': unusedImports,
|
|
24
|
+
import: fixupPluginRules(importPlugin),
|
|
25
|
+
'you-dont-need-lodash-underscore': fixupPluginRules(youDontNeedLodash),
|
|
26
|
+
},
|
|
27
|
+
languageOptions: {
|
|
28
|
+
parser: tseslint.parser,
|
|
29
|
+
ecmaVersion: 'latest',
|
|
30
|
+
sourceType: 'module',
|
|
31
|
+
},
|
|
32
|
+
rules: {
|
|
33
|
+
'no-unused-vars': 'off',
|
|
34
|
+
'@typescript-eslint/no-unused-vars': 'error',
|
|
35
|
+
'@typescript-eslint/no-explicit-any': 'warn',
|
|
36
|
+
'unused-imports/no-unused-imports': 'error',
|
|
37
|
+
'unused-imports/no-unused-vars': 'off',
|
|
38
|
+
'import/order': [
|
|
39
|
+
'error',
|
|
40
|
+
{
|
|
41
|
+
'newlines-between': 'always',
|
|
42
|
+
alphabetize: {
|
|
43
|
+
order: 'asc',
|
|
44
|
+
},
|
|
45
|
+
pathGroups: [
|
|
46
|
+
{
|
|
47
|
+
pattern: '@/**',
|
|
48
|
+
group: 'parent',
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
'prettier/prettier': [
|
|
54
|
+
'error',
|
|
55
|
+
{
|
|
56
|
+
singleQuote: true,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
'security/detect-object-injection': 'off',
|
|
60
|
+
'spaced-comment': 'error',
|
|
61
|
+
},
|
|
62
|
+
settings: {
|
|
63
|
+
'import/resolver': {
|
|
64
|
+
typescript: true,
|
|
65
|
+
node: true,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
prettier,
|
|
70
|
+
];
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import angular from 'angular-eslint';
|
|
2
|
+
|
|
3
|
+
import base from '../../base.mjs';
|
|
4
|
+
import json from '../json.mjs';
|
|
5
|
+
import storybook from '../storybook.mjs';
|
|
6
|
+
import yaml from '../yaml.mjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Angular ESLint configuration.
|
|
10
|
+
* Includes: base + JSON + YAML + Storybook + Angular rules
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```js
|
|
14
|
+
* import angular from '@etchteam/eslint-config/angular';
|
|
15
|
+
* export default angular;
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export default [
|
|
19
|
+
...base,
|
|
20
|
+
...json,
|
|
21
|
+
...yaml,
|
|
22
|
+
...storybook,
|
|
23
|
+
{
|
|
24
|
+
files: ['**/*.ts'],
|
|
25
|
+
extends: [...angular.configs.tsRecommended],
|
|
26
|
+
processor: angular.processInlineTemplates,
|
|
27
|
+
rules: {
|
|
28
|
+
'@angular-eslint/directive-selector': [
|
|
29
|
+
'error',
|
|
30
|
+
{
|
|
31
|
+
type: 'attribute',
|
|
32
|
+
prefix: 'app',
|
|
33
|
+
style: 'camelCase',
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
'@angular-eslint/component-selector': [
|
|
37
|
+
'error',
|
|
38
|
+
{
|
|
39
|
+
type: 'element',
|
|
40
|
+
prefix: 'app',
|
|
41
|
+
style: 'kebab-case',
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
files: ['**/*.html'],
|
|
48
|
+
extends: [
|
|
49
|
+
...angular.configs.templateRecommended,
|
|
50
|
+
...angular.configs.templateAccessibility,
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import nestjs from '@darraghor/eslint-plugin-nestjs-typed';
|
|
2
|
+
import globals from 'globals';
|
|
3
|
+
|
|
4
|
+
import base from '../../base.mjs';
|
|
5
|
+
import json from '../json.mjs';
|
|
6
|
+
import yaml from '../yaml.mjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* NestJS ESLint configuration.
|
|
10
|
+
* Includes: base + JSON + YAML + NestJS rules + Node.js/Jest globals
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```js
|
|
14
|
+
* import nestjs from '@etchteam/eslint-config/nestjs';
|
|
15
|
+
* export default nestjs;
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export default [
|
|
19
|
+
...base,
|
|
20
|
+
...json,
|
|
21
|
+
...yaml,
|
|
22
|
+
{
|
|
23
|
+
languageOptions: {
|
|
24
|
+
globals: {
|
|
25
|
+
...globals.node,
|
|
26
|
+
...globals.jest,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
nestjs.configs.flatRecommended,
|
|
31
|
+
];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import nextPlugin from '@next/eslint-plugin-next';
|
|
2
|
+
import reactHooks from 'eslint-plugin-react-hooks';
|
|
3
|
+
|
|
4
|
+
import base from '../../base.mjs';
|
|
5
|
+
import json from '../json.mjs';
|
|
6
|
+
import react from '../react.mjs';
|
|
7
|
+
import storybook from '../storybook.mjs';
|
|
8
|
+
import yaml from '../yaml.mjs';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Next.js ESLint configuration.
|
|
12
|
+
* Includes: base + JSON + YAML + Storybook + React + Next.js rules
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* ```js
|
|
16
|
+
* import nextjs from '@etchteam/eslint-config/nextjs';
|
|
17
|
+
* export default nextjs;
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export default [
|
|
21
|
+
...base,
|
|
22
|
+
...json,
|
|
23
|
+
...yaml,
|
|
24
|
+
...storybook,
|
|
25
|
+
...react,
|
|
26
|
+
{
|
|
27
|
+
plugins: {
|
|
28
|
+
'@next/next': nextPlugin,
|
|
29
|
+
'react-hooks': reactHooks,
|
|
30
|
+
},
|
|
31
|
+
rules: {
|
|
32
|
+
...nextPlugin.configs.recommended.rules,
|
|
33
|
+
...nextPlugin.configs['core-web-vitals'].rules,
|
|
34
|
+
...reactHooks.configs.recommended.rules,
|
|
35
|
+
'import/no-anonymous-default-export': 'warn',
|
|
36
|
+
'react/react-in-jsx-scope': 'off',
|
|
37
|
+
'react/prop-types': 'off',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import globals from 'globals';
|
|
2
|
+
|
|
3
|
+
import base from '../../base.mjs';
|
|
4
|
+
import json from '../json.mjs';
|
|
5
|
+
import yaml from '../yaml.mjs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Node.js backend ESLint configuration.
|
|
9
|
+
* Includes: base + JSON + YAML + Node.js globals
|
|
10
|
+
* Does NOT include: React, Storybook
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```js
|
|
14
|
+
* import nodejs from '@etchteam/eslint-config/nodejs';
|
|
15
|
+
* export default nodejs;
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export default [
|
|
19
|
+
...base,
|
|
20
|
+
...json,
|
|
21
|
+
...yaml,
|
|
22
|
+
{
|
|
23
|
+
languageOptions: {
|
|
24
|
+
globals: globals.node,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import base from '../../base.mjs';
|
|
2
|
+
import json from '../json.mjs';
|
|
3
|
+
import react from '../react.mjs';
|
|
4
|
+
import storybook from '../storybook.mjs';
|
|
5
|
+
import yaml from '../yaml.mjs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Preact ESLint configuration.
|
|
9
|
+
* Includes: base + JSON + YAML + Storybook + React (modified for Preact)
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* ```js
|
|
13
|
+
* import preact from '@etchteam/eslint-config/preact';
|
|
14
|
+
* export default preact;
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export default [
|
|
18
|
+
...base,
|
|
19
|
+
...json,
|
|
20
|
+
...yaml,
|
|
21
|
+
...storybook,
|
|
22
|
+
...react,
|
|
23
|
+
{
|
|
24
|
+
settings: {
|
|
25
|
+
react: {
|
|
26
|
+
pragma: 'h',
|
|
27
|
+
version: 'detect',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
rules: {
|
|
31
|
+
'react/prop-types': 'off',
|
|
32
|
+
'react/react-in-jsx-scope': 'off',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import lit from 'eslint-plugin-lit';
|
|
2
|
+
|
|
3
|
+
import base from '../../base.mjs';
|
|
4
|
+
import json from '../json.mjs';
|
|
5
|
+
import storybook from '../storybook.mjs';
|
|
6
|
+
import yaml from '../yaml.mjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Web Components (Lit) ESLint configuration.
|
|
10
|
+
* Includes: base + JSON + YAML + Storybook + Lit rules
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```js
|
|
14
|
+
* import webComponents from '@etchteam/eslint-config/web-components';
|
|
15
|
+
* export default webComponents;
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export default [
|
|
19
|
+
...base,
|
|
20
|
+
...json,
|
|
21
|
+
...yaml,
|
|
22
|
+
...storybook,
|
|
23
|
+
lit.configs['flat/recommended'],
|
|
24
|
+
];
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import jsxA11y from 'eslint-plugin-jsx-a11y';
|
|
2
|
+
import react from 'eslint-plugin-react';
|
|
3
|
+
|
|
4
|
+
import { fixupPluginRules } from '../utils/fixup.mjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* React and JSX accessibility linting configuration.
|
|
8
|
+
*/
|
|
9
|
+
export default [
|
|
10
|
+
{
|
|
11
|
+
files: ['**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}'],
|
|
12
|
+
plugins: {
|
|
13
|
+
react: fixupPluginRules(react),
|
|
14
|
+
'jsx-a11y': fixupPluginRules(jsxA11y),
|
|
15
|
+
},
|
|
16
|
+
rules: {
|
|
17
|
+
'jsx-a11y/anchor-ambiguous-text': 'error',
|
|
18
|
+
'jsx-a11y/no-aria-hidden-on-focusable': 'error',
|
|
19
|
+
'react/forbid-elements': [
|
|
20
|
+
'error',
|
|
21
|
+
{
|
|
22
|
+
forbid: [
|
|
23
|
+
{ element: 'b', message: 'Do not use HTML for styling' },
|
|
24
|
+
{ element: 'i', message: 'Do not use HTML for styling' },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
'react/jsx-no-useless-fragment': [
|
|
29
|
+
'error',
|
|
30
|
+
{
|
|
31
|
+
allowExpressions: true,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
'react/prefer-read-only-props': 'error',
|
|
35
|
+
},
|
|
36
|
+
settings: {
|
|
37
|
+
react: {
|
|
38
|
+
version: 'detect',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
];
|
package/src/index.mjs
CHANGED
|
@@ -1,101 +1,36 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import prettier from 'eslint-plugin-prettier/recommended';
|
|
7
|
-
import react from 'eslint-plugin-react';
|
|
8
|
-
import security from 'eslint-plugin-security';
|
|
9
|
-
import storybook from 'eslint-plugin-storybook';
|
|
10
|
-
import unusedImports from 'eslint-plugin-unused-imports';
|
|
11
|
-
import yml from 'eslint-plugin-yml';
|
|
12
|
-
import youDontNeedLodash from 'eslint-plugin-you-dont-need-lodash-underscore';
|
|
13
|
-
import tseslint from 'typescript-eslint';
|
|
1
|
+
import base from './base.mjs';
|
|
2
|
+
import json from './configs/json.mjs';
|
|
3
|
+
import reactConfig from './configs/react.mjs';
|
|
4
|
+
import storybook from './configs/storybook.mjs';
|
|
5
|
+
import yaml from './configs/yaml.mjs';
|
|
14
6
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
{
|
|
22
|
-
files: ['**/*.json'],
|
|
23
|
-
...json.configs.recommended,
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
plugins: {
|
|
27
|
-
// Plugins with native flat config support
|
|
28
|
-
'unused-imports': unusedImports,
|
|
7
|
+
// Named exports for composable configs
|
|
8
|
+
export { default as base } from './base.mjs';
|
|
9
|
+
export { default as json } from './configs/json.mjs';
|
|
10
|
+
export { default as react } from './configs/react.mjs';
|
|
11
|
+
export { default as storybook } from './configs/storybook.mjs';
|
|
12
|
+
export { default as yaml } from './configs/yaml.mjs';
|
|
29
13
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
order: 'asc',
|
|
54
|
-
},
|
|
55
|
-
pathGroups: [
|
|
56
|
-
{
|
|
57
|
-
pattern: '@/**',
|
|
58
|
-
group: 'parent',
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
'prettier/prettier': [
|
|
64
|
-
'error',
|
|
65
|
-
{
|
|
66
|
-
singleQuote: true,
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
'jsx-a11y/anchor-ambiguous-text': 'error',
|
|
70
|
-
'jsx-a11y/no-aria-hidden-on-focusable': 'error',
|
|
71
|
-
'security/detect-object-injection': 'off',
|
|
72
|
-
'react/forbid-elements': [
|
|
73
|
-
'error',
|
|
74
|
-
{
|
|
75
|
-
forbid: [
|
|
76
|
-
{ element: 'b', message: 'Do not use HTML for styling' },
|
|
77
|
-
{ element: 'i', message: 'Do not use HTML for styling' },
|
|
78
|
-
],
|
|
79
|
-
},
|
|
80
|
-
],
|
|
81
|
-
'react/jsx-no-useless-fragment': [
|
|
82
|
-
'error',
|
|
83
|
-
{
|
|
84
|
-
allowExpressions: true,
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
'react/prefer-read-only-props': 'error',
|
|
88
|
-
'spaced-comment': 'error',
|
|
89
|
-
},
|
|
90
|
-
settings: {
|
|
91
|
-
'import/resolver': {
|
|
92
|
-
typescript: true,
|
|
93
|
-
node: true,
|
|
94
|
-
},
|
|
95
|
-
react: {
|
|
96
|
-
version: 'detect',
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
prettier, // Prettier recommended config
|
|
101
|
-
];
|
|
14
|
+
/**
|
|
15
|
+
* Default export - Full ESLint configuration (backwards compatible)
|
|
16
|
+
* Includes: base + JSON + YAML + Storybook + React
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* ```js
|
|
20
|
+
* import etchConfig from '@etchteam/eslint-config';
|
|
21
|
+
* export default etchConfig;
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* For environment-specific or composable usage, use named exports:
|
|
25
|
+
* ```js
|
|
26
|
+
* import { base, react } from '@etchteam/eslint-config';
|
|
27
|
+
* export default [...base, ...react];
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Or import specific environment configs:
|
|
31
|
+
* ```js
|
|
32
|
+
* import nextjs from '@etchteam/eslint-config/nextjs';
|
|
33
|
+
* export default nextjs;
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export default [...base, ...json, ...yaml, ...storybook, ...reactConfig];
|
package/src/types.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
|
|
3
|
+
type FlatConfigArray = Linter.Config[];
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Base ESLint configuration for all projects.
|
|
7
|
+
* Includes: JavaScript, TypeScript, security, import ordering, prettier, and common rules.
|
|
8
|
+
*/
|
|
9
|
+
export declare const base: FlatConfigArray;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* JSON file linting configuration.
|
|
13
|
+
*/
|
|
14
|
+
export declare const json: FlatConfigArray;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* YAML file linting configuration.
|
|
18
|
+
*/
|
|
19
|
+
export declare const yaml: FlatConfigArray;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Storybook linting configuration.
|
|
23
|
+
*/
|
|
24
|
+
export declare const storybook: FlatConfigArray;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* React and JSX accessibility linting configuration.
|
|
28
|
+
*/
|
|
29
|
+
export declare const react: FlatConfigArray;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Node.js backend ESLint configuration.
|
|
33
|
+
* Includes: base + JSON + YAML + Node.js globals
|
|
34
|
+
*/
|
|
35
|
+
export declare const nodejs: FlatConfigArray;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Next.js ESLint configuration.
|
|
39
|
+
* Includes: base + JSON + YAML + Storybook + React + Next.js rules
|
|
40
|
+
*/
|
|
41
|
+
export declare const nextjs: FlatConfigArray;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Preact ESLint configuration.
|
|
45
|
+
* Includes: base + JSON + YAML + Storybook + React (modified for Preact)
|
|
46
|
+
*/
|
|
47
|
+
export declare const preact: FlatConfigArray;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Angular ESLint configuration.
|
|
51
|
+
* Includes: base + JSON + YAML + Storybook + Angular rules
|
|
52
|
+
*/
|
|
53
|
+
export declare const angular: FlatConfigArray;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Web Components (Lit) ESLint configuration.
|
|
57
|
+
* Includes: base + JSON + YAML + Storybook + Lit rules
|
|
58
|
+
*/
|
|
59
|
+
export declare const webComponents: FlatConfigArray;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* NestJS ESLint configuration.
|
|
63
|
+
* Includes: base + JSON + YAML + NestJS rules + Node.js/Jest globals
|
|
64
|
+
*/
|
|
65
|
+
export declare const nestjs: FlatConfigArray;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Default export - Full ESLint configuration (backwards compatible)
|
|
69
|
+
* Includes: base + JSON + YAML + Storybook + React
|
|
70
|
+
*/
|
|
71
|
+
declare const config: FlatConfigArray;
|
|
72
|
+
export default config;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { fixupPluginRules } from '@eslint/compat';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wraps plugins that don't yet support ESLint 9 flat config natively.
|
|
5
|
+
* This provides a centralized place to manage compatibility wrappers.
|
|
6
|
+
*/
|
|
7
|
+
export { fixupPluginRules };
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Helper to wrap multiple plugins at once
|
|
11
|
+
* @param {Record<string, object>} plugins - Object mapping plugin names to plugin modules
|
|
12
|
+
* @returns {Record<string, object>} - Object with wrapped plugins
|
|
13
|
+
*/
|
|
14
|
+
export function fixupPlugins(plugins) {
|
|
15
|
+
return Object.fromEntries(
|
|
16
|
+
Object.entries(plugins).map(([name, plugin]) => [
|
|
17
|
+
name,
|
|
18
|
+
fixupPluginRules(plugin),
|
|
19
|
+
]),
|
|
20
|
+
);
|
|
21
|
+
}
|