eslint-plugin-traceability 1.7.0 → 1.8.0
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 +82 -0
- package/README.md +73 -32
- package/docs/ci-cd-pipeline.md +224 -0
- package/docs/cli-integration.md +22 -0
- package/docs/code-quality-refactor-opportunities-2025-12-03.md +78 -0
- package/docs/config-presets.md +38 -0
- package/docs/conventional-commits-guide.md +185 -0
- package/docs/custom-rules-development-guide.md +659 -0
- package/docs/decisions/0001-allow-dynamic-require-for-built-plugins.md +26 -0
- package/docs/decisions/001-typescript-for-eslint-plugin.accepted.md +111 -0
- package/docs/decisions/002-jest-for-eslint-testing.accepted.md +137 -0
- package/docs/decisions/003-code-quality-ratcheting-plan.md +48 -0
- package/docs/decisions/004-automated-version-bumping-for-ci-cd.md +196 -0
- package/docs/decisions/005-github-actions-validation-tooling.accepted.md +144 -0
- package/docs/decisions/006-semantic-release-for-automated-publishing.accepted.md +227 -0
- package/docs/decisions/007-github-releases-over-changelog.accepted.md +216 -0
- package/docs/decisions/008-ci-audit-flags.accepted.md +60 -0
- package/docs/decisions/009-security-focused-lint-rules.accepted.md +64 -0
- package/docs/decisions/010-implements-annotation-for-multi-story-requirements.proposed.md +184 -0
- package/docs/decisions/adr-0001-console-usage-for-cli-guards.md +190 -0
- package/docs/decisions/adr-accept-dev-dep-risk-glob.md +40 -0
- package/docs/decisions/adr-commit-branch-tests.md +54 -0
- package/docs/decisions/adr-maintenance-cli-interface.md +140 -0
- package/docs/decisions/adr-pre-push-parity.md +112 -0
- package/docs/decisions/code-quality-ratcheting-plan.md +53 -0
- package/docs/dependency-health.md +238 -0
- package/docs/eslint-9-setup-guide.md +517 -0
- package/docs/eslint-plugin-development-guide.md +487 -0
- package/docs/functionality-coverage-2025-12-03.md +250 -0
- package/docs/jest-testing-guide.md +100 -0
- package/docs/rules/prefer-implements-annotation.md +219 -0
- package/docs/rules/require-branch-annotation.md +71 -0
- package/docs/rules/require-req-annotation.md +203 -0
- package/docs/rules/require-story-annotation.md +159 -0
- package/docs/rules/valid-annotation-format.md +418 -0
- package/docs/rules/valid-req-reference.md +153 -0
- package/docs/rules/valid-story-reference.md +120 -0
- package/docs/security-incidents/2025-11-17-glob-cli-incident.md +45 -0
- package/docs/security-incidents/2025-11-18-brace-expansion-redos.md +45 -0
- package/docs/security-incidents/2025-11-18-bundled-dev-deps-accepted-risk.md +93 -0
- package/docs/security-incidents/2025-11-18-tar-race-condition.md +43 -0
- package/docs/security-incidents/2025-12-03-dependency-health-review.md +58 -0
- package/docs/security-incidents/SECURITY-INCIDENT-2025-11-18-semantic-release-bundled-npm.known-error.md +104 -0
- package/docs/security-incidents/SECURITY-INCIDENT-TEMPLATE.md +37 -0
- package/docs/security-incidents/dependency-override-rationale.md +57 -0
- package/docs/security-incidents/dev-deps-high.json +116 -0
- package/docs/security-incidents/handling-procedure.md +54 -0
- package/docs/stories/001.0-DEV-PLUGIN-SETUP.story.md +92 -0
- package/docs/stories/002.0-DEV-ESLINT-CONFIG.story.md +82 -0
- package/docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md +112 -0
- package/docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md +153 -0
- package/docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md +138 -0
- package/docs/stories/006.0-DEV-FILE-VALIDATION.story.md +144 -0
- package/docs/stories/007.0-DEV-ERROR-REPORTING.story.md +163 -0
- package/docs/stories/008.0-DEV-AUTO-FIX.story.md +150 -0
- package/docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md +117 -0
- package/docs/stories/010.0-DEV-DEEP-VALIDATION.story.md +124 -0
- package/docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md +149 -0
- package/docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md +216 -0
- package/docs/stories/010.3-DEV-MIGRATE-TO-IMPLEMENTS.story.md +236 -0
- package/docs/stories/developer-story.map.md +120 -0
- package/docs/ts-jest-presets-guide.md +548 -0
- package/lib/src/index.d.ts +2 -2
- package/lib/src/index.js +2 -0
- package/lib/src/maintenance/batch.d.ts +5 -0
- package/lib/src/maintenance/batch.js +5 -0
- package/lib/src/maintenance/cli.js +34 -212
- package/lib/src/maintenance/commands.d.ts +32 -0
- package/lib/src/maintenance/commands.js +139 -0
- package/lib/src/maintenance/detect.d.ts +2 -0
- package/lib/src/maintenance/detect.js +4 -0
- package/lib/src/maintenance/flags.d.ts +99 -0
- package/lib/src/maintenance/flags.js +121 -0
- package/lib/src/maintenance/report.d.ts +2 -0
- package/lib/src/maintenance/report.js +2 -0
- package/lib/src/maintenance/update.d.ts +4 -0
- package/lib/src/maintenance/update.js +4 -0
- package/lib/src/rules/helpers/require-story-io.d.ts +3 -0
- package/lib/src/rules/helpers/require-story-io.js +20 -6
- package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +30 -0
- package/lib/src/rules/helpers/valid-annotation-format-internal.js +36 -0
- package/lib/src/rules/helpers/valid-annotation-options.js +15 -4
- package/lib/src/rules/helpers/valid-annotation-utils.js +5 -0
- package/lib/src/rules/helpers/valid-implements-utils.d.ts +75 -0
- package/lib/src/rules/helpers/valid-implements-utils.js +149 -0
- package/lib/src/rules/helpers/valid-story-reference-helpers.d.ts +3 -4
- package/lib/src/rules/prefer-implements-annotation.d.ts +39 -0
- package/lib/src/rules/prefer-implements-annotation.js +276 -0
- package/lib/src/rules/valid-annotation-format.js +87 -28
- package/lib/src/rules/valid-req-reference.js +71 -0
- package/lib/src/utils/reqAnnotationDetection.d.ts +4 -1
- package/lib/src/utils/reqAnnotationDetection.js +43 -15
- package/lib/tests/maintenance/cli.test.js +89 -0
- package/lib/tests/plugin-default-export-and-configs.test.js +3 -0
- package/lib/tests/rules/prefer-implements-annotation.test.d.ts +1 -0
- package/lib/tests/rules/prefer-implements-annotation.test.js +84 -0
- package/lib/tests/rules/require-req-annotation.test.js +8 -1
- package/lib/tests/rules/require-story-annotation.test.js +9 -4
- package/lib/tests/rules/valid-annotation-format.test.js +78 -0
- package/lib/tests/rules/valid-req-reference.test.js +34 -0
- package/lib/tests/utils/ts-language-options.d.ts +1 -7
- package/lib/tests/utils/ts-language-options.js +8 -5
- package/package.json +7 -3
- package/user-docs/api-reference.md +507 -0
- package/user-docs/eslint-9-setup-guide.md +639 -0
- package/user-docs/examples.md +74 -0
- package/user-docs/migration-guide.md +158 -0
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
# ESLint 9 Setup Guide
|
|
2
|
+
|
|
3
|
+
Created autonomously by [voder.ai](https://voder.ai)
|
|
4
|
+
Applies to projects using eslint-plugin-traceability 1.x with ESLint 9 flat config. For the current plugin version and release notes, see GitHub Releases: <https://github.com/voder-ai/eslint-plugin-traceability/releases>.
|
|
5
|
+
|
|
6
|
+
This guide shows how to properly set up ESLint 9 with flat configuration format. ESLint 9 uses flat config by default and has several important changes from previous versions.
|
|
7
|
+
|
|
8
|
+
## Table of Contents
|
|
9
|
+
|
|
10
|
+
- [Quick Setup](#quick-setup)
|
|
11
|
+
- [Configuration File Format](#configuration-file-format)
|
|
12
|
+
- [ESM vs CommonJS Config Files](#esm-vs-commonjs-config-files)
|
|
13
|
+
- [Common Configuration Patterns](#common-configuration-patterns)
|
|
14
|
+
- [Package.json Scripts](#packagejson-scripts)
|
|
15
|
+
- [TypeScript Integration](#typescript-integration)
|
|
16
|
+
- [Common Issues and Solutions](#common-issues-and-solutions)
|
|
17
|
+
- [Troubleshooting ESLint Configuration](#troubleshooting-eslint-configuration)
|
|
18
|
+
- [Working Example](#working-example)
|
|
19
|
+
|
|
20
|
+
## Quick Setup
|
|
21
|
+
|
|
22
|
+
### 1. Install Dependencies
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Core ESLint v9
|
|
26
|
+
npm install --save-dev eslint@^9.39.1
|
|
27
|
+
|
|
28
|
+
# Recommended configurations
|
|
29
|
+
npm install --save-dev @eslint/js@^9.39.1
|
|
30
|
+
|
|
31
|
+
# For TypeScript projects
|
|
32
|
+
npm install --save-dev @typescript-eslint/parser@^8.0.0
|
|
33
|
+
npm install --save-dev @typescript-eslint/utils@^8.0.0
|
|
34
|
+
|
|
35
|
+
# For testing (if using Jest)
|
|
36
|
+
npm install --save-dev @types/eslint@^9.0.0
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Create Configuration File
|
|
40
|
+
|
|
41
|
+
Create `eslint.config.js` (not `.eslintrc.*`):
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
import js from "@eslint/js";
|
|
45
|
+
|
|
46
|
+
export default [
|
|
47
|
+
js.configs.recommended,
|
|
48
|
+
{
|
|
49
|
+
files: ["**/*.js", "**/*.mjs"],
|
|
50
|
+
rules: {
|
|
51
|
+
// Your custom rules here
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 3. Add Scripts to package.json
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"scripts": {
|
|
62
|
+
"lint": "eslint .",
|
|
63
|
+
"lint:fix": "eslint . --fix"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 4. Enable Traceability Plugin
|
|
69
|
+
|
|
70
|
+
To integrate the traceability plugin, update your `eslint.config.js` to include its recommended configuration:
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
import js from "@eslint/js";
|
|
74
|
+
import traceability from "eslint-plugin-traceability";
|
|
75
|
+
|
|
76
|
+
export default [js.configs.recommended, traceability.configs.recommended];
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Configuration File Format
|
|
80
|
+
|
|
81
|
+
### Key Changes from ESLintRC
|
|
82
|
+
|
|
83
|
+
- **File name**: `eslint.config.js` (not `.eslintrc.*`)
|
|
84
|
+
- **Format**: Array of configuration objects (not single object)
|
|
85
|
+
- **Import style**: ES modules by default
|
|
86
|
+
- **No extends**: Use imports and spread syntax instead
|
|
87
|
+
|
|
88
|
+
### Basic Structure
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
// eslint.config.js
|
|
92
|
+
import js from "@eslint/js";
|
|
93
|
+
|
|
94
|
+
export default [
|
|
95
|
+
// Apply to all files
|
|
96
|
+
js.configs.recommended,
|
|
97
|
+
|
|
98
|
+
// Specific configuration objects
|
|
99
|
+
{
|
|
100
|
+
files: ["**/*.js"], // File patterns
|
|
101
|
+
languageOptions: {
|
|
102
|
+
ecmaVersion: 2024,
|
|
103
|
+
sourceType: "module",
|
|
104
|
+
},
|
|
105
|
+
rules: {
|
|
106
|
+
// Rule configurations
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
// Ignore patterns
|
|
111
|
+
{
|
|
112
|
+
ignores: ["dist/**", "build/**", "node_modules/**"],
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## ESM vs CommonJS Config Files
|
|
118
|
+
|
|
119
|
+
ESLint 9's flat config system works with both ESM and CommonJS configs; which one you use depends on your Node setup:
|
|
120
|
+
|
|
121
|
+
- **ESM (recommended for new projects)**
|
|
122
|
+
- Use `eslint.config.js` or `eslint.config.mjs` that exports with `export default [...]`.
|
|
123
|
+
- Your `package.json` typically has `{ "type": "module" }`, or you use the `.mjs` extension.
|
|
124
|
+
- Examples in this guide that use `import ... from` and `export default [...]` assume an ESM config.
|
|
125
|
+
|
|
126
|
+
- **CommonJS**
|
|
127
|
+
- Use `eslint.config.cjs` or `eslint.config.js` with `module.exports = [...]`.
|
|
128
|
+
- Your `package.json` typically omits `"type": "module"` (or explicitly sets `"type": "commonjs"`).
|
|
129
|
+
- This style matches the example in the project README that shows `module.exports = [...]`.
|
|
130
|
+
|
|
131
|
+
Both forms are supported by ESLint 9 as long as the file extension and `package.json` `type` setting are consistent. Pick the style that matches the rest of your Node tooling and stick to it across your project.
|
|
132
|
+
|
|
133
|
+
## Common Configuration Patterns
|
|
134
|
+
|
|
135
|
+
### 1. JavaScript Only Project
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
// eslint.config.js
|
|
139
|
+
import js from "@eslint/js";
|
|
140
|
+
|
|
141
|
+
export default [
|
|
142
|
+
js.configs.recommended,
|
|
143
|
+
{
|
|
144
|
+
files: ["**/*.js", "**/*.mjs"],
|
|
145
|
+
languageOptions: {
|
|
146
|
+
ecmaVersion: 2024,
|
|
147
|
+
sourceType: "module",
|
|
148
|
+
},
|
|
149
|
+
rules: {
|
|
150
|
+
"no-unused-vars": "error",
|
|
151
|
+
"no-console": "warn",
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
ignores: ["dist/**", "build/**"],
|
|
156
|
+
},
|
|
157
|
+
];
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### 2. TypeScript Project
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
// eslint.config.js
|
|
164
|
+
import js from "@eslint/js";
|
|
165
|
+
import typescriptParser from "@typescript-eslint/parser";
|
|
166
|
+
|
|
167
|
+
export default [
|
|
168
|
+
js.configs.recommended,
|
|
169
|
+
{
|
|
170
|
+
files: ["**/*.ts", "**/*.tsx"],
|
|
171
|
+
languageOptions: {
|
|
172
|
+
parser: typescriptParser,
|
|
173
|
+
parserOptions: {
|
|
174
|
+
project: "./tsconfig.json",
|
|
175
|
+
tsconfigRootDir: import.meta.dirname,
|
|
176
|
+
ecmaVersion: 2024,
|
|
177
|
+
sourceType: "module",
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
rules: {
|
|
181
|
+
"@typescript-eslint/no-unused-vars": "error",
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
files: ["**/*.js", "**/*.mjs"],
|
|
186
|
+
languageOptions: {
|
|
187
|
+
ecmaVersion: 2024,
|
|
188
|
+
sourceType: "module",
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Mixed JavaScript/TypeScript Projects
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
// eslint.config.js
|
|
198
|
+
import js from "@eslint/js";
|
|
199
|
+
import typescriptParser from "@typescript-eslint/parser";
|
|
200
|
+
|
|
201
|
+
export default [
|
|
202
|
+
js.configs.recommended,
|
|
203
|
+
{
|
|
204
|
+
files: ["**/*.{js,jsx,ts,tsx}"],
|
|
205
|
+
languageOptions: {
|
|
206
|
+
parser: typescriptParser,
|
|
207
|
+
parserOptions: {
|
|
208
|
+
project: "./tsconfig.json",
|
|
209
|
+
tsconfigRootDir: import.meta.dirname,
|
|
210
|
+
ecmaVersion: 2024,
|
|
211
|
+
sourceType: "module",
|
|
212
|
+
},
|
|
213
|
+
ecmaVersion: 2024,
|
|
214
|
+
sourceType: "module",
|
|
215
|
+
},
|
|
216
|
+
rules: {
|
|
217
|
+
// Combined JS and TS rules
|
|
218
|
+
"no-unused-vars": "error",
|
|
219
|
+
"@typescript-eslint/no-unused-vars": "error",
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
];
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 3. Node.js Configuration Files (CommonJS)
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
// eslint.config.js
|
|
229
|
+
export default [
|
|
230
|
+
{
|
|
231
|
+
// Config files that use CommonJS
|
|
232
|
+
files: ["*.config.js", "*.config.mjs", "jest.config.js"],
|
|
233
|
+
languageOptions: {
|
|
234
|
+
ecmaVersion: 2024,
|
|
235
|
+
sourceType: "commonjs",
|
|
236
|
+
globals: {
|
|
237
|
+
require: "readonly",
|
|
238
|
+
module: "readonly",
|
|
239
|
+
exports: "readonly",
|
|
240
|
+
__dirname: "readonly",
|
|
241
|
+
__filename: "readonly",
|
|
242
|
+
console: "readonly",
|
|
243
|
+
process: "readonly",
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
];
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### 4. Test Files (Jest/Vitest)
|
|
251
|
+
|
|
252
|
+
```javascript
|
|
253
|
+
// eslint.config.js
|
|
254
|
+
export default [
|
|
255
|
+
{
|
|
256
|
+
files: [
|
|
257
|
+
"**/*.test.{js,ts}",
|
|
258
|
+
"**/__tests__/**/*.{js,ts}",
|
|
259
|
+
"**/tests/**/*.{js,ts}",
|
|
260
|
+
],
|
|
261
|
+
languageOptions: {
|
|
262
|
+
globals: {
|
|
263
|
+
describe: "readonly",
|
|
264
|
+
it: "readonly",
|
|
265
|
+
test: "readonly",
|
|
266
|
+
expect: "readonly",
|
|
267
|
+
beforeEach: "readonly",
|
|
268
|
+
afterEach: "readonly",
|
|
269
|
+
beforeAll: "readonly",
|
|
270
|
+
afterAll: "readonly",
|
|
271
|
+
jest: "readonly",
|
|
272
|
+
vi: "readonly", // for Vitest
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
];
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Monorepos / Workspaces
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
// eslint.config.js
|
|
283
|
+
import js from "@eslint/js";
|
|
284
|
+
import typescriptParser from "@typescript-eslint/parser";
|
|
285
|
+
|
|
286
|
+
export default [
|
|
287
|
+
js.configs.recommended,
|
|
288
|
+
{
|
|
289
|
+
// Lint all packages in a monorepo/workspace
|
|
290
|
+
files: ["packages/*/src/**/*.{js,ts,tsx}"],
|
|
291
|
+
languageOptions: {
|
|
292
|
+
parser: typescriptParser,
|
|
293
|
+
parserOptions: {
|
|
294
|
+
project: ["./packages/*/tsconfig.json"],
|
|
295
|
+
tsconfigRootDir: import.meta.dirname,
|
|
296
|
+
ecmaVersion: 2024,
|
|
297
|
+
sourceType: "module",
|
|
298
|
+
},
|
|
299
|
+
ecmaVersion: 2024,
|
|
300
|
+
sourceType: "module",
|
|
301
|
+
},
|
|
302
|
+
rules: {
|
|
303
|
+
// Monorepo-specific rules
|
|
304
|
+
"no-unused-vars": "error",
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
];
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Package.json Scripts
|
|
311
|
+
|
|
312
|
+
### Recommended Scripts
|
|
313
|
+
|
|
314
|
+
```json
|
|
315
|
+
{
|
|
316
|
+
"scripts": {
|
|
317
|
+
"lint": "eslint .",
|
|
318
|
+
"lint:fix": "eslint . --fix",
|
|
319
|
+
"lint:check": "eslint . --max-warnings 0"
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### For Plugin Development (with Build Step)
|
|
325
|
+
|
|
326
|
+
```json
|
|
327
|
+
{
|
|
328
|
+
"scripts": {
|
|
329
|
+
"prelint": "npm run build",
|
|
330
|
+
"build": "tsc",
|
|
331
|
+
"lint": "eslint .",
|
|
332
|
+
"lint:fix": "eslint . --fix"
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## TypeScript Integration
|
|
338
|
+
|
|
339
|
+
### Parser Configuration
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
// eslint.config.js
|
|
343
|
+
import typescriptParser from "@typescript-eslint/parser";
|
|
344
|
+
|
|
345
|
+
export default [
|
|
346
|
+
{
|
|
347
|
+
files: ["**/*.ts", "**/*.tsx"],
|
|
348
|
+
languageOptions: {
|
|
349
|
+
parser: typescriptParser, // Import the parser object directly
|
|
350
|
+
parserOptions: {
|
|
351
|
+
project: "./tsconfig.json",
|
|
352
|
+
tsconfigRootDir: import.meta.dirname, // Use import.meta.dirname in ESM
|
|
353
|
+
ecmaVersion: 2024,
|
|
354
|
+
sourceType: "module",
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
];
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Common TypeScript Rules
|
|
362
|
+
|
|
363
|
+
```javascript
|
|
364
|
+
export default [
|
|
365
|
+
{
|
|
366
|
+
files: ["**/*.ts", "**/*.tsx"],
|
|
367
|
+
rules: {
|
|
368
|
+
"@typescript-eslint/no-unused-vars": "error",
|
|
369
|
+
"@typescript-eslint/explicit-function-return-type": "warn",
|
|
370
|
+
"@typescript-eslint/no-explicit-any": "warn",
|
|
371
|
+
"@typescript-eslint/prefer-const": "error",
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
];
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Common Issues and Solutions
|
|
378
|
+
|
|
379
|
+
### Issue: "Expected object with parse() method"
|
|
380
|
+
|
|
381
|
+
**Problem**: Using `require.resolve()` for parser
|
|
382
|
+
|
|
383
|
+
```javascript
|
|
384
|
+
// ❌ Wrong
|
|
385
|
+
languageOptions: {
|
|
386
|
+
parser: require.resolve("@typescript-eslint/parser");
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
**Solution**: Import parser directly
|
|
391
|
+
|
|
392
|
+
```javascript
|
|
393
|
+
// ✅ Correct
|
|
394
|
+
import typescriptParser from "@typescript-eslint/parser";
|
|
395
|
+
|
|
396
|
+
languageOptions: {
|
|
397
|
+
parser: typescriptParser;
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Issue: "eslint:recommended" not working
|
|
402
|
+
|
|
403
|
+
**Problem**: Using string reference
|
|
404
|
+
|
|
405
|
+
```javascript
|
|
406
|
+
// ❌ Wrong
|
|
407
|
+
export default ["eslint:recommended"];
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
**Solution**: Import from @eslint/js
|
|
411
|
+
|
|
412
|
+
```javascript
|
|
413
|
+
// ✅ Correct
|
|
414
|
+
import js from "@eslint/js";
|
|
415
|
+
|
|
416
|
+
export default [js.configs.recommended];
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Issue: CLI flags not working
|
|
420
|
+
|
|
421
|
+
**Problem**: Using deprecated flags
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
# ❌ Wrong (deprecated in flat config)
|
|
425
|
+
eslint src --ext .ts --config eslint.config.js
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
**Solution**: Use file patterns in config
|
|
429
|
+
|
|
430
|
+
```bash
|
|
431
|
+
# ✅ Correct
|
|
432
|
+
eslint .
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Issue: Globals not defined
|
|
436
|
+
|
|
437
|
+
**Problem**: Missing environment globals
|
|
438
|
+
|
|
439
|
+
```javascript
|
|
440
|
+
// ❌ Wrong - globals not defined
|
|
441
|
+
export default [
|
|
442
|
+
{
|
|
443
|
+
files: ["**/*.js"],
|
|
444
|
+
// Missing globals for Node.js/browser
|
|
445
|
+
},
|
|
446
|
+
];
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**Solution**: Define globals explicitly
|
|
450
|
+
|
|
451
|
+
```javascript
|
|
452
|
+
// ✅ Correct
|
|
453
|
+
export default [
|
|
454
|
+
{
|
|
455
|
+
files: ["**/*.js"],
|
|
456
|
+
languageOptions: {
|
|
457
|
+
globals: {
|
|
458
|
+
console: "readonly",
|
|
459
|
+
process: "readonly",
|
|
460
|
+
Buffer: "readonly",
|
|
461
|
+
// etc.
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
];
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Troubleshooting ESLint Configuration
|
|
469
|
+
|
|
470
|
+
The following scenarios cover common issues when configuring ESLint 9 with flat config, especially in mixed JavaScript and TypeScript projects.
|
|
471
|
+
|
|
472
|
+
### Mixed JavaScript/TypeScript Projects
|
|
473
|
+
|
|
474
|
+
Problem: ESLint does not correctly apply rules to `.js`, `.jsx`, `.ts`, or `.tsx` files when using separate file patterns or incorrect parser configuration.
|
|
475
|
+
|
|
476
|
+
Solution: Use combined file patterns or separate override blocks, and import the parser correctly. For example:
|
|
477
|
+
|
|
478
|
+
```javascript
|
|
479
|
+
// eslint.config.js
|
|
480
|
+
import js from "@eslint/js";
|
|
481
|
+
import typescriptParser from "@typescript-eslint/parser";
|
|
482
|
+
|
|
483
|
+
export default [
|
|
484
|
+
js.configs.recommended,
|
|
485
|
+
{
|
|
486
|
+
files: ["**/*.{js,jsx,ts,tsx}"],
|
|
487
|
+
languageOptions: {
|
|
488
|
+
parser: typescriptParser,
|
|
489
|
+
parserOptions: {
|
|
490
|
+
project: "./tsconfig.json",
|
|
491
|
+
tsconfigRootDir: import.meta.dirname,
|
|
492
|
+
ecmaVersion: 2024,
|
|
493
|
+
sourceType: "module",
|
|
494
|
+
},
|
|
495
|
+
ecmaVersion: 2024,
|
|
496
|
+
sourceType: "module",
|
|
497
|
+
},
|
|
498
|
+
rules: {
|
|
499
|
+
// Combined JS and TS rules
|
|
500
|
+
"no-unused-vars": "error",
|
|
501
|
+
"@typescript-eslint/no-unused-vars": "error",
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
];
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
## Working Example
|
|
508
|
+
|
|
509
|
+
Here's a complete working configuration for a TypeScript ESLint plugin project:
|
|
510
|
+
|
|
511
|
+
```javascript
|
|
512
|
+
// eslint.config.js
|
|
513
|
+
import js from "@eslint/js";
|
|
514
|
+
import typescriptParser from "@typescript-eslint/parser";
|
|
515
|
+
|
|
516
|
+
// Conditional plugin loading (for plugin development)
|
|
517
|
+
let plugin;
|
|
518
|
+
try {
|
|
519
|
+
plugin = await import("./lib/index.js");
|
|
520
|
+
} catch {
|
|
521
|
+
console.warn("Plugin not built yet, skipping traceability rules");
|
|
522
|
+
plugin = {};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
export default [
|
|
526
|
+
js.configs.recommended,
|
|
527
|
+
{
|
|
528
|
+
// Node.js config files (CommonJS)
|
|
529
|
+
files: ["*.config.js", "*.config.mjs", "jest.config.js"],
|
|
530
|
+
languageOptions: {
|
|
531
|
+
ecmaVersion: 2024,
|
|
532
|
+
sourceType: "commonjs",
|
|
533
|
+
globals: {
|
|
534
|
+
require: "readonly",
|
|
535
|
+
module: "readonly",
|
|
536
|
+
exports: "readonly",
|
|
537
|
+
__dirname: "readonly",
|
|
538
|
+
__filename: "readonly",
|
|
539
|
+
console: "readonly",
|
|
540
|
+
process: "readonly",
|
|
541
|
+
},
|
|
542
|
+
},
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
// TypeScript files
|
|
546
|
+
files: ["**/*.ts", "**/*.tsx"],
|
|
547
|
+
languageOptions: {
|
|
548
|
+
parser: typescriptParser,
|
|
549
|
+
parserOptions: {
|
|
550
|
+
project: "./tsconfig.json",
|
|
551
|
+
tsconfigRootDir: import.meta.dirname,
|
|
552
|
+
ecmaVersion: 2024,
|
|
553
|
+
sourceType: "module",
|
|
554
|
+
},
|
|
555
|
+
},
|
|
556
|
+
plugins: {
|
|
557
|
+
...(plugin.rules ? { traceability: plugin } : {}),
|
|
558
|
+
},
|
|
559
|
+
rules: {
|
|
560
|
+
"@typescript-eslint/no-unused-vars": "error",
|
|
561
|
+
},
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
// JavaScript files
|
|
565
|
+
files: ["**/*.js", "**/*.mjs"],
|
|
566
|
+
languageOptions: {
|
|
567
|
+
ecmaVersion: 2024,
|
|
568
|
+
sourceType: "module",
|
|
569
|
+
},
|
|
570
|
+
plugins: {
|
|
571
|
+
...(plugin.rules ? { traceability: plugin } : {}),
|
|
572
|
+
},
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
// Test files
|
|
576
|
+
files: [
|
|
577
|
+
"**/*.test.{js,ts}",
|
|
578
|
+
"**/__tests__/**/*.{js,ts}",
|
|
579
|
+
"**/tests/**/*.{js,ts}",
|
|
580
|
+
],
|
|
581
|
+
languageOptions: {
|
|
582
|
+
globals: {
|
|
583
|
+
describe: "readonly",
|
|
584
|
+
it: "readonly",
|
|
585
|
+
test: "readonly",
|
|
586
|
+
expect: "readonly",
|
|
587
|
+
beforeEach: "readonly",
|
|
588
|
+
afterEach: "readonly",
|
|
589
|
+
beforeAll: "readonly",
|
|
590
|
+
afterAll: "readonly",
|
|
591
|
+
jest: "readonly",
|
|
592
|
+
},
|
|
593
|
+
},
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
// Ignore patterns
|
|
597
|
+
ignores: [
|
|
598
|
+
"lib/**",
|
|
599
|
+
"dist/**",
|
|
600
|
+
"build/**",
|
|
601
|
+
"node_modules/**",
|
|
602
|
+
"coverage/**",
|
|
603
|
+
],
|
|
604
|
+
},
|
|
605
|
+
];
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
### Corresponding package.json:
|
|
609
|
+
|
|
610
|
+
```json
|
|
611
|
+
{
|
|
612
|
+
"scripts": {
|
|
613
|
+
"prelint": "npm run build",
|
|
614
|
+
"build": "tsc",
|
|
615
|
+
"lint": "eslint .",
|
|
616
|
+
"lint:fix": "eslint . --fix",
|
|
617
|
+
"type-check": "tsc --noEmit"
|
|
618
|
+
},
|
|
619
|
+
"devDependencies": {
|
|
620
|
+
"@eslint/js": "^9.39.1",
|
|
621
|
+
"@typescript-eslint/parser": "^8.46.4",
|
|
622
|
+
"@typescript-eslint/utils": "^8.46.4",
|
|
623
|
+
"eslint": "^9.39.1",
|
|
624
|
+
"typescript": "^5.9.3"
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
## Key Takeaways
|
|
630
|
+
|
|
631
|
+
1. **Use `eslint.config.js`**, not `.eslintrc.*`
|
|
632
|
+
2. **Import configurations**, don't use string references
|
|
633
|
+
3. **Import parsers directly**, don't use `require.resolve()`
|
|
634
|
+
4. **Define globals explicitly** for different environments
|
|
635
|
+
5. **Use file patterns** instead of CLI `--ext` flags
|
|
636
|
+
6. **Structure as array of objects**, each targeting specific file types
|
|
637
|
+
7. **Use `ignores`** instead of `.eslintignore` files
|
|
638
|
+
|
|
639
|
+
This setup provides a solid foundation for ESLint 9 that works reliably across different project types and environments.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
Created autonomously by [voder.ai](https://voder.ai).
|
|
4
|
+
Examples are written for the eslint-plugin-traceability 1.x series. For the latest published version and full release history, see GitHub Releases: <https://github.com/voder-ai/eslint-plugin-traceability/releases>.
|
|
5
|
+
|
|
6
|
+
This document provides runnable examples demonstrating how to use the `eslint-plugin-traceability` plugin in real-world scenarios.
|
|
7
|
+
|
|
8
|
+
## 1. ESLint Flat Config with Recommended Preset
|
|
9
|
+
|
|
10
|
+
Create an ESLint config file (`eslint.config.js`) at your project root:
|
|
11
|
+
|
|
12
|
+
```javascript
|
|
13
|
+
// eslint.config.js
|
|
14
|
+
import js from "@eslint/js";
|
|
15
|
+
import traceability from "eslint-plugin-traceability";
|
|
16
|
+
|
|
17
|
+
export default [js.configs.recommended, traceability.configs.recommended];
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Then run ESLint on your source files:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx eslint "src/**/*.ts"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 2. Using the Strict Preset
|
|
27
|
+
|
|
28
|
+
If you want to enforce all traceability rules (strict mode), update your config:
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
// eslint.config.js
|
|
32
|
+
import js from "@eslint/js";
|
|
33
|
+
import traceability from "eslint-plugin-traceability";
|
|
34
|
+
|
|
35
|
+
export default [js.configs.recommended, traceability.configs.strict];
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Run ESLint the same way:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx eslint "src/**/*.js"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 3. CLI Invocation Example
|
|
45
|
+
|
|
46
|
+
You can use the plugin without a config file by specifying rules inline:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npx eslint --no-eslintrc \
|
|
50
|
+
--rule "traceability/require-story-annotation:error" \
|
|
51
|
+
--rule "traceability/require-req-annotation:error" \
|
|
52
|
+
sample.js
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
- `--no-eslintrc` tells ESLint to ignore user configs.
|
|
56
|
+
- `--rule` options enable the traceability rules you need.
|
|
57
|
+
|
|
58
|
+
Replace `sample.js` with your JavaScript or TypeScript file.
|
|
59
|
+
|
|
60
|
+
## 4. Linting a Specific Directory
|
|
61
|
+
|
|
62
|
+
Add an npm script in your `package.json`:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
"scripts": {
|
|
66
|
+
"lint:trace": "eslint \"src/**/*.{js,ts}\" --config eslint.config.js"
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Then run:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm run lint:trace
|
|
74
|
+
```
|