@codfish/eslint-config 0.0.0-PR-155--2a9a213 → 0.0.0-PR-125--8d3b55f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -159
- package/dist/dapp.d.ts +1 -1
- package/dist/docker.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/rules/config-files.d.ts +1 -1
- package/dist/rules/jest.d.ts +3 -0
- package/dist/rules/jest.d.ts.map +1 -0
- package/dist/rules/react.d.ts +1 -1
- package/dist/rules/vitest.d.ts +3 -0
- package/dist/rules/vitest.d.ts.map +1 -0
- package/dist/utils.d.ts +0 -5
- package/dist/utils.d.ts.map +1 -1
- package/index.js +31 -143
- package/package.json +26 -38
- package/rules/jest.js +34 -0
- package/rules/react.js +17 -49
- package/rules/vitest.js +39 -0
- package/utils.js +5 -13
- package/dist/rules/tests.d.ts +0 -3
- package/dist/rules/tests.d.ts.map +0 -1
- package/dist/rules/typescript.d.ts +0 -38
- package/dist/rules/typescript.d.ts.map +0 -1
- package/dist/tests/integration/eslint-execution.spec.d.ts +0 -2
- package/dist/tests/integration/eslint-execution.spec.d.ts.map +0 -1
- package/dist/tests/integration/react-integration.spec.d.ts +0 -2
- package/dist/tests/integration/react-integration.spec.d.ts.map +0 -1
- package/dist/tests/integration/rule-application.spec.d.ts +0 -2
- package/dist/tests/integration/rule-application.spec.d.ts.map +0 -1
- package/dist/tests/scenarios/edge-cases.spec.d.ts +0 -2
- package/dist/tests/scenarios/edge-cases.spec.d.ts.map +0 -1
- package/dist/tests/unit/config-loading.spec.d.ts +0 -2
- package/dist/tests/unit/config-loading.spec.d.ts.map +0 -1
- package/dist/tests/unit/dynamic-detection.spec.d.ts +0 -2
- package/dist/tests/unit/dynamic-detection.spec.d.ts.map +0 -1
- package/dist/tests/unit/utils.spec.d.ts +0 -2
- package/dist/tests/unit/utils.spec.d.ts.map +0 -1
- package/dist/vitest.config.d.ts +0 -3
- package/dist/vitest.config.d.ts.map +0 -1
- package/rules/tests.js +0 -52
- package/rules/typescript.js +0 -56
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @codfish/eslint-config
|
|
2
2
|
|
|
3
3
|
> Modern ESLint configuration with TypeScript, React/Next.js, YAML, Testing Library, and testing framework support using
|
|
4
|
-
> ESLint
|
|
4
|
+
> ESLint v9+ flat config format.
|
|
5
5
|
|
|
6
6
|
[](http://npm.im/@codfish/eslint-config)
|
|
7
7
|
[](http://npm-stat.com/charts.html?package=@codfish/eslint-config&from=2015-08-01)
|
|
@@ -18,16 +18,10 @@
|
|
|
18
18
|
- [Installation](#installation)
|
|
19
19
|
- [Usage](#usage)
|
|
20
20
|
- [Opinionated Highlights](#opinionated-highlights)
|
|
21
|
-
- [IDE Setup](#ide-setup)
|
|
22
|
-
- [VS Code / Cursor](#vs-code--cursor)
|
|
23
21
|
- [Prettier Configuration](#prettier-configuration)
|
|
24
22
|
- [Use in combination with prettier-plugin-tailwindcss](#use-in-combination-with-prettier-plugin-tailwindcss)
|
|
25
23
|
- [Example scripts](#example-scripts)
|
|
26
24
|
- [Commitlint Configuration](#commitlint-configuration)
|
|
27
|
-
- [Upgrading to ESLint 10](#upgrading-to-eslint-10)
|
|
28
|
-
- [Breaking Changes in ESLint 10](#breaking-changes-in-eslint-10)
|
|
29
|
-
- [Migration Steps](#migration-steps)
|
|
30
|
-
- [What Changed](#what-changed)
|
|
31
25
|
- [Migration from Legacy Config](#migration-from-legacy-config)
|
|
32
26
|
|
|
33
27
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
@@ -35,14 +29,14 @@
|
|
|
35
29
|
|
|
36
30
|
## Features
|
|
37
31
|
|
|
38
|
-
- **Modern ESLint
|
|
32
|
+
- **Modern ESLint v9+ flat config**: Uses the new flat configuration format
|
|
39
33
|
- **Dynamic feature detection**: Automatically configures based on your project's dependencies
|
|
40
34
|
- **TypeScript support**: Full TypeScript linting with modern typescript-eslint parser and rules
|
|
41
35
|
- **React ecosystem**: React, React Hooks, and JSX accessibility rules when React is detected
|
|
42
36
|
- **Next.js support**: Automatically configures Next.js official plugin linting rules when detected
|
|
43
37
|
- **Test framework agnostic**: Supports Jest and Vitest with automatic detection
|
|
44
38
|
- **Testing Library integration**: Automatically includes Testing Library rules for test files
|
|
45
|
-
- **
|
|
39
|
+
- **YAML/YML support**: Built-in linting for YAML configuration files
|
|
46
40
|
- **Prettier integration**: Built-in Prettier configuration with conflict resolution via eslint-config-prettier
|
|
47
41
|
- **ESM architecture**: Built with ECMAScript modules and full TypeScript typing
|
|
48
42
|
- **Docker support**: Optional configuration for dockerized applications
|
|
@@ -53,35 +47,9 @@
|
|
|
53
47
|
Install the package and required peer dependencies:
|
|
54
48
|
|
|
55
49
|
```sh
|
|
56
|
-
npm i -D eslint@
|
|
57
|
-
|
|
58
|
-
# Optionally, you can uninstall plugins or presets you don't need to manage anymore,
|
|
59
|
-
# @codfish/eslint-config includes them all.
|
|
60
|
-
npm uninstall typescript-eslint \
|
|
61
|
-
eslint-config-prettier \
|
|
62
|
-
eslint-plugin-jest \
|
|
63
|
-
eslint-plugin-jsx-a11y \
|
|
64
|
-
eslint-plugin-prettier \
|
|
65
|
-
eslint-plugin-react \
|
|
66
|
-
eslint-plugin-react-hooks \
|
|
67
|
-
@tanstack/eslint-plugin-query \
|
|
68
|
-
eslint-plugin-simple-import-sort \
|
|
69
|
-
eslint-plugin-testing-library \
|
|
70
|
-
eslint-plugin-yml \
|
|
71
|
-
@next/eslint-plugin-next \
|
|
72
|
-
eslint-plugin-next \
|
|
73
|
-
commitlint \
|
|
74
|
-
@commitlint/cli \
|
|
75
|
-
@commitlint/config-conventional \
|
|
76
|
-
prettier # optional, see note
|
|
50
|
+
npm i -D eslint@9 @codfish/eslint-config
|
|
77
51
|
```
|
|
78
52
|
|
|
79
|
-
> [!NOTE]
|
|
80
|
-
>
|
|
81
|
-
> ESLint now handles linting and formatting for JavaScript, TypeScript, Markdown, HTML, JSON, and YAML files
|
|
82
|
-
> automatically. If you want to format additional file types (like CSS, SCSS, etc.), you can leave Prettier installed as
|
|
83
|
-
> a dev dependency in your project.
|
|
84
|
-
|
|
85
53
|
## Usage
|
|
86
54
|
|
|
87
55
|
Create an `eslint.config.js` file in your project root:
|
|
@@ -177,11 +145,6 @@ import codfish from '@codfish/eslint-config';
|
|
|
177
145
|
export default defineConfig(
|
|
178
146
|
codfish,
|
|
179
147
|
|
|
180
|
-
// Custom ignores
|
|
181
|
-
{
|
|
182
|
-
ignores: ['some-directory'],
|
|
183
|
-
},
|
|
184
|
-
|
|
185
148
|
{
|
|
186
149
|
files: ['**/*.spec.{js,ts,jsx,tsx}'],
|
|
187
150
|
rules: {
|
|
@@ -287,47 +250,10 @@ This configuration includes some opinionated settings that you might want to cus
|
|
|
287
250
|
See the [configuration examples below](#usage) for instructions on overriding these settings to match your team's
|
|
288
251
|
preferences.
|
|
289
252
|
|
|
290
|
-
## IDE Setup
|
|
291
|
-
|
|
292
|
-
### VS Code / Cursor
|
|
293
|
-
|
|
294
|
-
For the best development experience with VS Code or Cursor (or any VS Code-based IDE), install the
|
|
295
|
-
[ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) and configure it to
|
|
296
|
-
auto-fix on save:
|
|
297
|
-
|
|
298
|
-
Add these settings to your `.vscode/settings.json` or user settings:
|
|
299
|
-
|
|
300
|
-
```json
|
|
301
|
-
{
|
|
302
|
-
"editor.codeActionsOnSave": {
|
|
303
|
-
"source.fixAll": "explicit"
|
|
304
|
-
},
|
|
305
|
-
"eslint.validate": [
|
|
306
|
-
"javascript",
|
|
307
|
-
"javascriptreact",
|
|
308
|
-
"typescript",
|
|
309
|
-
"typescriptreact",
|
|
310
|
-
"markdown",
|
|
311
|
-
"json",
|
|
312
|
-
"jsonc",
|
|
313
|
-
"html",
|
|
314
|
-
"yml",
|
|
315
|
-
"yaml"
|
|
316
|
-
]
|
|
317
|
-
}
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
This configuration enables:
|
|
321
|
-
|
|
322
|
-
- Automatic linting and formatting on save for all supported file types
|
|
323
|
-
- ESLint validation for Markdown, JSON, YAML, and HTML files
|
|
324
|
-
- A unified development experience across your entire codebase
|
|
325
|
-
|
|
326
253
|
## Prettier Configuration
|
|
327
254
|
|
|
328
|
-
**Prettier is included and runs automatically** through ESLint for JavaScript, TypeScript, JSX, TSX
|
|
329
|
-
|
|
330
|
-
Prettier separately** for these file types.
|
|
255
|
+
**Prettier is included and runs automatically** through ESLint for JavaScript, TypeScript, JSX, and TSX files using the
|
|
256
|
+
[built-in configuration](./prettier.js). **You don't need to install or configure Prettier separately** for basic usage.
|
|
331
257
|
|
|
332
258
|
You can then override the default config by creating your own Prettier config file, or extend the built-in config:
|
|
333
259
|
|
|
@@ -380,20 +306,25 @@ export default {
|
|
|
380
306
|
};
|
|
381
307
|
```
|
|
382
308
|
|
|
309
|
+
> [!TIP]
|
|
310
|
+
>
|
|
311
|
+
> If you want to format other file types (like Markdown, JSON, CSS, or YAML) or run Prettier directly, you can install
|
|
312
|
+
> it as a dev dependency: `npm i -D prettier`.
|
|
313
|
+
|
|
383
314
|
### Use in combination with prettier-plugin-tailwindcss
|
|
384
315
|
|
|
385
316
|
```sh
|
|
386
|
-
npm i -D eslint@
|
|
317
|
+
npm i -D eslint@9 @codfish/eslint-config prettier-plugin-tailwindcss
|
|
387
318
|
```
|
|
388
319
|
|
|
389
320
|
```js
|
|
390
321
|
// prettier.config.js
|
|
391
322
|
|
|
392
|
-
import
|
|
323
|
+
import codfishPrettier from '@codfish/eslint-config/prettier';
|
|
393
324
|
|
|
394
325
|
/** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */
|
|
395
326
|
export default {
|
|
396
|
-
...
|
|
327
|
+
...codfishPrettier,
|
|
397
328
|
plugins: ['prettier-plugin-tailwindcss'],
|
|
398
329
|
tailwindStylesheet: './src/styles/app.css',
|
|
399
330
|
tailwindFunctions: ['clsx'], // optional
|
|
@@ -404,7 +335,7 @@ export default {
|
|
|
404
335
|
|
|
405
336
|
Optionally, you can add these scripts to your `package.json` for common linting workflows:
|
|
406
337
|
|
|
407
|
-
**
|
|
338
|
+
**Basic scripts (no separate Prettier installation needed):**
|
|
408
339
|
|
|
409
340
|
```json
|
|
410
341
|
{
|
|
@@ -413,32 +344,24 @@ Optionally, you can add these scripts to your `package.json` for common linting
|
|
|
413
344
|
"fix": "eslint . --fix"
|
|
414
345
|
},
|
|
415
346
|
"lint-staged": {
|
|
416
|
-
"*.{js,jsx,ts,tsx
|
|
347
|
+
"*.{js,jsx,ts,tsx}": ["eslint --fix"]
|
|
417
348
|
}
|
|
418
349
|
}
|
|
419
350
|
```
|
|
420
351
|
|
|
421
|
-
|
|
422
|
-
>
|
|
423
|
-
> ESLint now handles linting and formatting for JavaScript, TypeScript, Markdown, HTML, JSON, and YAML files. You don't
|
|
424
|
-
> need to run Prettier separately for these file types.
|
|
425
|
-
|
|
426
|
-
**With Prettier for other file types (CSS, SCSS, etc.):**
|
|
427
|
-
|
|
428
|
-
If you want to format additional file types not covered by ESLint (like CSS, SCSS), you can install Prettier and add
|
|
429
|
-
these scripts:
|
|
352
|
+
**With Prettier installed separately (for formatting non-JS files):**
|
|
430
353
|
|
|
431
354
|
```json
|
|
432
355
|
{
|
|
433
356
|
"scripts": {
|
|
434
357
|
"lint": "eslint .",
|
|
435
358
|
"fix": "eslint . --fix",
|
|
436
|
-
"format": "prettier --write \"**/*.{css,
|
|
359
|
+
"format": "prettier --config ./node_modules/@codfish/eslint-config/prettier.js --write \"**/*.{json,css,md}\"",
|
|
437
360
|
"check": "npm run lint && npm run format -- --check --no-write"
|
|
438
361
|
},
|
|
439
362
|
"lint-staged": {
|
|
440
|
-
"*.{js,jsx,ts,tsx
|
|
441
|
-
"*.{css,
|
|
363
|
+
"*.{js,jsx,ts,tsx}": ["eslint --fix"],
|
|
364
|
+
"*.{json,css,md}": ["prettier --write --config ./node_modules/@codfish/eslint-config/prettier.js"]
|
|
442
365
|
}
|
|
443
366
|
}
|
|
444
367
|
```
|
|
@@ -505,72 +428,11 @@ jobs:
|
|
|
505
428
|
--verbose
|
|
506
429
|
```
|
|
507
430
|
|
|
508
|
-
## Upgrading to ESLint 10
|
|
509
|
-
|
|
510
|
-
This package now requires **ESLint 10.0.0 or higher** and **Node.js v20.19.0 or higher**.
|
|
511
|
-
|
|
512
|
-
### Breaking Changes in ESLint 10
|
|
513
|
-
|
|
514
|
-
- **ESLint 10 Required**: Minimum ESLint version is now 10.0.0
|
|
515
|
-
- **Node.js v20.19.0+**: Minimum Node.js version increased from v20.0.0 to v20.19.0
|
|
516
|
-
- **Legacy eslintrc removed**: ESLint 10 completely removes the deprecated eslintrc config system (this package already
|
|
517
|
-
uses flat config)
|
|
518
|
-
- **Improved JSX tracking**: ESLint 10 properly tracks JSX references in scope analysis, which may surface previously
|
|
519
|
-
hidden unused import warnings in React files
|
|
520
|
-
- **New recommended rules**: Three new rules enabled in `eslint:recommended`:
|
|
521
|
-
- `no-unassigned-vars` - Disallow variables that are assigned but never used
|
|
522
|
-
- `no-useless-assignment` - Disallow assignments that don't change the value
|
|
523
|
-
- `preserve-caught-error` - Enforce that caught errors are not reassigned
|
|
524
|
-
|
|
525
|
-
### Migration Steps
|
|
526
|
-
|
|
527
|
-
1. **Update Node.js** (if needed):
|
|
528
|
-
|
|
529
|
-
```sh
|
|
530
|
-
node --version # Ensure you're on v20.19.0+ or v22.13.0+
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
2. **Update ESLint and this config**:
|
|
534
|
-
|
|
535
|
-
```sh
|
|
536
|
-
npm install --save-dev eslint@10 @codfish/eslint-config@latest
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
3. **Install dependencies with legacy peer deps** (required until all plugins update):
|
|
540
|
-
|
|
541
|
-
```sh
|
|
542
|
-
npm install --legacy-peer-deps
|
|
543
|
-
```
|
|
544
|
-
|
|
545
|
-
This is necessary because some ESLint plugins haven't updated their `peerDependencies` to include ESLint 10 yet. The
|
|
546
|
-
plugins still work correctly with ESLint 10.
|
|
547
|
-
|
|
548
|
-
4. **Run linting** and check for new violations:
|
|
549
|
-
|
|
550
|
-
```sh
|
|
551
|
-
npm run lint
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
5. **Review React files** for newly reported unused imports. ESLint 10's improved JSX tracking may flag imports that
|
|
555
|
-
were previously ignored but are actually used in JSX.
|
|
556
|
-
|
|
557
|
-
### What Changed
|
|
558
|
-
|
|
559
|
-
Since this package already uses ESLint's flat config format (the biggest change in ESLint 9), the upgrade to ESLint 10
|
|
560
|
-
is relatively smooth. The main changes are:
|
|
561
|
-
|
|
562
|
-
- ✅ Flat config format (already implemented)
|
|
563
|
-
- ✅ Plugin configurations updated to ESLint 10-compatible versions
|
|
564
|
-
- ✅ All tests passing with ESLint 10
|
|
565
|
-
- ⚠️ Some plugins show peer dependency warnings but work correctly (ecosystem is catching up)
|
|
566
|
-
|
|
567
|
-
For more details, see the [ESLint 10 Migration Guide](https://eslint.org/docs/latest/use/migrate-to-10.0.0).
|
|
568
|
-
|
|
569
431
|
## Migration from Legacy Config
|
|
570
432
|
|
|
571
433
|
If you're upgrading from an older version that used Airbnb presets:
|
|
572
434
|
|
|
573
|
-
1. **Update to ESLint
|
|
435
|
+
1. **Update to ESLint v9+**: `npm install --save-dev eslint@9`
|
|
574
436
|
2. **Switch to flat config**: Replace `.eslintrc.js` with `eslint.config.js`
|
|
575
437
|
3. **Use import syntax**: Change from `require()` to `import` statements
|
|
576
438
|
4. **Remove explicit React config**: React support is now automatically detected
|
package/dist/dapp.d.ts
CHANGED
package/dist/docker.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jest.d.ts","sourceRoot":"","sources":["../../rules/jest.js"],"names":[],"mappings":""}
|
package/dist/rules/react.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../../rules/vitest.js"],"names":[],"mappings":""}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get the version of a dependency from the consumer's package.json.
|
|
3
|
-
* Returns the major version as a string (e.g. '18', '19'), or null if not found.
|
|
4
|
-
*/
|
|
5
|
-
export function getDepVersion(dep: any): string | null;
|
|
6
1
|
export function hasLocalConfig(moduleName: any, searchOptions?: {}): boolean;
|
|
7
2
|
export function hasDep(props: any): boolean;
|
|
8
3
|
export function hasDevDep(props: any): boolean;
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.js"],"names":[],"mappings":"AA4BA,6EAKC;AAfgC,4CAA+D;AAA/D,+CAA+D;AAA/D,gDAA+D;AAMzF,8CAA8E;AAE9E,yDAAmE"}
|
package/index.js
CHANGED
|
@@ -1,39 +1,33 @@
|
|
|
1
1
|
import js from '@eslint/js';
|
|
2
|
-
import json from '@eslint/json';
|
|
3
|
-
import markdown from '@eslint/markdown';
|
|
4
|
-
import html from '@html-eslint/eslint-plugin';
|
|
5
|
-
import htmlParser from '@html-eslint/parser';
|
|
6
2
|
import { defineConfig } from 'eslint/config';
|
|
7
|
-
import
|
|
3
|
+
import prettier from 'eslint-plugin-prettier/recommended';
|
|
8
4
|
import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort';
|
|
9
5
|
import ymlPlugin from 'eslint-plugin-yml';
|
|
10
6
|
import globals from 'globals';
|
|
7
|
+
import tseslint from 'typescript-eslint';
|
|
11
8
|
|
|
12
9
|
import prettierBuiltInConfig from './prettier.js';
|
|
13
10
|
import configFilesConfig from './rules/config-files.js';
|
|
11
|
+
import jestConfig from './rules/jest.js';
|
|
14
12
|
import reactConfig from './rules/react.js';
|
|
15
|
-
import
|
|
16
|
-
import tseslintConfig, { rules as tsRules } from './rules/typescript.js';
|
|
13
|
+
import vitestConfig from './rules/vitest.js';
|
|
17
14
|
import { hasLocalConfig, ifAnyDep } from './utils.js';
|
|
15
|
+
|
|
18
16
|
const useBuiltinPrettierConfig = !hasLocalConfig('prettier');
|
|
19
17
|
|
|
20
18
|
/**
|
|
21
|
-
* Modern ESLint configuration with dynamic feature detection
|
|
22
|
-
* Supports TypeScript, React, Vitest, Prettier, YAML, and
|
|
23
|
-
*
|
|
24
|
-
* React ESLint configuration. Includes React, React Hooks, and JSX accessibility rules.
|
|
25
|
-
* - https://github.com/jsx-eslint/eslint-plugin-react
|
|
26
|
-
* - https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks
|
|
27
|
-
* - https://github.com/jsx-eslint/eslint-plugin-jsx-a11y
|
|
19
|
+
* Modern ESLint configuration with dynamic feature detection
|
|
20
|
+
* Supports TypeScript, React, Jest, Vitest, Prettier, YAML, and Next.js
|
|
28
21
|
*/
|
|
29
22
|
export default defineConfig([
|
|
30
|
-
// Base
|
|
31
|
-
|
|
32
|
-
name: 'codfish/base',
|
|
23
|
+
// Base JavaScript configuration
|
|
24
|
+
js.configs.recommended,
|
|
33
25
|
|
|
34
|
-
|
|
26
|
+
tseslint.configs.recommended,
|
|
35
27
|
|
|
36
|
-
|
|
28
|
+
// Base configuration for all files
|
|
29
|
+
{
|
|
30
|
+
name: 'codfish/base',
|
|
37
31
|
|
|
38
32
|
plugins: {
|
|
39
33
|
'simple-import-sort': simpleImportSortPlugin,
|
|
@@ -42,9 +36,6 @@ export default defineConfig([
|
|
|
42
36
|
languageOptions: {
|
|
43
37
|
ecmaVersion: 'latest',
|
|
44
38
|
sourceType: 'module',
|
|
45
|
-
parserOptions: {
|
|
46
|
-
ecmaFeatures: { jsx: true },
|
|
47
|
-
},
|
|
48
39
|
globals: {
|
|
49
40
|
...globals.browser,
|
|
50
41
|
...globals.node,
|
|
@@ -53,22 +44,6 @@ export default defineConfig([
|
|
|
53
44
|
},
|
|
54
45
|
|
|
55
46
|
rules: {
|
|
56
|
-
// Error handling rules to enforce using the Error object
|
|
57
|
-
'no-throw-literal': 'error',
|
|
58
|
-
'prefer-promise-reject-errors': 'error',
|
|
59
|
-
'no-unused-vars': ['error', { ignoreRestSiblings: true }],
|
|
60
|
-
'no-empty-function': 'off',
|
|
61
|
-
|
|
62
|
-
// Asynchronous functions that don't use await might not need to be asynchronous functions
|
|
63
|
-
// Usually result of refactoring, leads to misunderstanding/misusage
|
|
64
|
-
'require-await': 'error',
|
|
65
|
-
|
|
66
|
-
// Disallow console statements in regular code (only allowed in test files)
|
|
67
|
-
'no-console': 'error',
|
|
68
|
-
|
|
69
|
-
// Consolidate your imports
|
|
70
|
-
'no-duplicate-imports': ['error', { includeExports: false }],
|
|
71
|
-
|
|
72
47
|
// Custom Grouping: https://github.com/lydell/eslint-plugin-simple-import-sort#custom-grouping
|
|
73
48
|
// Examples: https://github.com/lydell/eslint-plugin-simple-import-sort/blob/main/examples/.eslintrc.js
|
|
74
49
|
'simple-import-sort/imports': [
|
|
@@ -87,58 +62,32 @@ export default defineConfig([
|
|
|
87
62
|
},
|
|
88
63
|
],
|
|
89
64
|
'simple-import-sort/exports': 'error',
|
|
90
|
-
'sort-imports': 'off',
|
|
91
65
|
|
|
92
|
-
//
|
|
66
|
+
// 2. Encouraging `lodash-es` imports per file
|
|
93
67
|
// lodash imports should use `lodash-es` package and should be imported per file.
|
|
94
|
-
// E.G: `import get from
|
|
68
|
+
// E.G: `import get from 'lodash-es/get'`
|
|
95
69
|
// More details in https://stackoverflow.com/questions/35250500/correct-way-to-import-lodash#answer-35251059
|
|
96
|
-
// 2. Prevent relative imports - use path aliases instead
|
|
97
|
-
// Use `@/` for src imports and `@tests/` for test imports
|
|
98
|
-
// 3. Prevent vitest globals imports - these are available globally
|
|
99
70
|
'no-restricted-imports': [
|
|
100
71
|
'error',
|
|
101
72
|
{
|
|
102
73
|
paths: [
|
|
103
74
|
{
|
|
104
75
|
name: 'lodash',
|
|
105
|
-
message:
|
|
76
|
+
message: "Please use lodash-es direct import E.G: `import get from 'lodash-es/get'`",
|
|
106
77
|
},
|
|
107
78
|
{
|
|
108
79
|
name: 'lodash-es',
|
|
109
|
-
message:
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
name: 'jest',
|
|
113
|
-
importNames: ['describe', 'expect', 'test', 'it', 'jest'],
|
|
114
|
-
message:
|
|
115
|
-
'These jest globals (describe, expect, test, it, jest) are available globally and should not be imported. Remove this import statement.',
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
name: 'vitest',
|
|
119
|
-
importNames: ['describe', 'expect', 'test', 'it', 'vi'],
|
|
120
|
-
message:
|
|
121
|
-
'These vitest globals (describe, expect, test, it, vi) are available globally and should not be imported. Remove this import statement.',
|
|
80
|
+
message: "Please use lodash-es direct import E.G: `import get from 'lodash-es/get'`",
|
|
122
81
|
},
|
|
123
82
|
],
|
|
124
83
|
patterns: [
|
|
125
84
|
{
|
|
126
85
|
group: ['lodash/*'],
|
|
127
|
-
message:
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
// Prevent relative imports going back 1+ directories. Use @/ or @tests/ aliases instead.
|
|
131
|
-
// Ensures consistent and cleaner import paths, and avoids confusing import hell with deeply nested files.
|
|
132
|
-
group: ['../*', '../../*', '../../../*', '../../../../*'],
|
|
133
|
-
message:
|
|
134
|
-
'Relative imports going back 1+ directories are not allowed. Use path aliases: @/ for src/*, @tests/ for tests/* imports. For example, instead of `import x from "../components/*"`, use `import x from "@/components/*"`',
|
|
86
|
+
message: "Please use lodash-es direct import E.G: `import get from 'lodash-es/get'`",
|
|
135
87
|
},
|
|
136
88
|
],
|
|
137
89
|
},
|
|
138
90
|
],
|
|
139
|
-
|
|
140
|
-
// TypeScript rules (empty object when typescript is not installed)
|
|
141
|
-
...tsRules,
|
|
142
91
|
},
|
|
143
92
|
},
|
|
144
93
|
|
|
@@ -153,6 +102,7 @@ export default defineConfig([
|
|
|
153
102
|
'coverage',
|
|
154
103
|
'.vercel',
|
|
155
104
|
'**/logs/',
|
|
105
|
+
'bin/*',
|
|
156
106
|
'**/dist/',
|
|
157
107
|
'**/dist-ssr/',
|
|
158
108
|
'**/cache/',
|
|
@@ -183,34 +133,15 @@ export default defineConfig([
|
|
|
183
133
|
'.expo',
|
|
184
134
|
'**/tmp/',
|
|
185
135
|
'**/temp/',
|
|
186
|
-
'
|
|
187
|
-
'.
|
|
188
|
-
'**/.eslintcache',
|
|
136
|
+
'.tmp',
|
|
137
|
+
'.eslintcache',
|
|
189
138
|
'*.tsbuildinfo',
|
|
190
|
-
'node_modules',
|
|
191
|
-
'**/node_modules/',
|
|
192
|
-
'**/pnpm-lock.yaml',
|
|
193
|
-
'**/pnpm-lock.*.yaml',
|
|
194
|
-
'.history',
|
|
195
|
-
'**/.yarn',
|
|
196
|
-
'**/yarn.lock',
|
|
197
|
-
'**/package-lock.json',
|
|
198
|
-
'**/.yarnrc.yml',
|
|
199
|
-
'pacts',
|
|
200
|
-
'.claude',
|
|
201
|
-
'.__mf__temp',
|
|
202
139
|
],
|
|
203
140
|
},
|
|
204
141
|
|
|
205
142
|
// Configuration files (eslint, prettier, etc.)
|
|
206
143
|
configFilesConfig,
|
|
207
144
|
|
|
208
|
-
// React configuration (dynamic)
|
|
209
|
-
ifAnyDep('react', reactConfig, []),
|
|
210
|
-
|
|
211
|
-
// Jest OR Vitest configuration (dynamic)
|
|
212
|
-
ifAnyDep(['jest', 'vitest'], testConfig, []),
|
|
213
|
-
|
|
214
145
|
// YML files
|
|
215
146
|
ymlPlugin.configs['flat/standard'],
|
|
216
147
|
ymlPlugin.configs['flat/prettier'], // handles conflicting rules with the yml plugin
|
|
@@ -225,67 +156,24 @@ export default defineConfig([
|
|
|
225
156
|
},
|
|
226
157
|
},
|
|
227
158
|
|
|
228
|
-
//
|
|
229
|
-
|
|
230
|
-
name: 'codfish/json',
|
|
231
|
-
files: ['**/*.json'],
|
|
232
|
-
ignores: ['**/tsconfig*.json', '**/package-lock.json'],
|
|
233
|
-
plugins: { json },
|
|
234
|
-
language: 'json/json',
|
|
235
|
-
extends: ['json/recommended'],
|
|
236
|
-
},
|
|
237
|
-
|
|
238
|
-
// JSONC files (JSON with Comments) - for files that allow comments
|
|
239
|
-
{
|
|
240
|
-
name: 'codfish/jsonc',
|
|
241
|
-
files: ['**/*.jsonc'],
|
|
242
|
-
plugins: { json },
|
|
243
|
-
language: 'json/jsonc',
|
|
244
|
-
extends: ['json/recommended'],
|
|
245
|
-
},
|
|
246
|
-
|
|
247
|
-
// JSON5 files - for TypeScript configs (supports comments AND trailing commas)
|
|
248
|
-
{
|
|
249
|
-
name: 'codfish/json5',
|
|
250
|
-
files: ['**/tsconfig*.json', '**/*.json5'],
|
|
251
|
-
plugins: { json },
|
|
252
|
-
language: 'json/json5',
|
|
253
|
-
extends: ['json/recommended'],
|
|
254
|
-
},
|
|
159
|
+
// React configuration (dynamic)
|
|
160
|
+
ifAnyDep('react', reactConfig, []),
|
|
255
161
|
|
|
256
|
-
//
|
|
257
|
-
|
|
258
|
-
name: 'codfish/markdown',
|
|
259
|
-
files: ['**/*.md'],
|
|
260
|
-
plugins: { markdown },
|
|
261
|
-
extends: ['markdown/recommended'],
|
|
262
|
-
rules: {
|
|
263
|
-
// Allow GitHub-style alerts and checkbox syntax (task lists)
|
|
264
|
-
'markdown/no-missing-label-refs': [
|
|
265
|
-
'error',
|
|
266
|
-
{ allowLabels: ['!NOTE', '!WARNING', '!IMPORTANT', '!TIP', '!CAUTION', '', 'x', 'X'] },
|
|
267
|
-
],
|
|
268
|
-
},
|
|
269
|
-
},
|
|
162
|
+
// Jest OR Vitest configuration (dynamic)
|
|
163
|
+
ifAnyDep('jest', jestConfig, []),
|
|
270
164
|
|
|
271
|
-
//
|
|
272
|
-
|
|
273
|
-
name: 'codfish/html',
|
|
274
|
-
files: ['**/*.html'],
|
|
275
|
-
plugins: { html },
|
|
276
|
-
languageOptions: { parser: htmlParser },
|
|
277
|
-
},
|
|
165
|
+
// Vitest configuration (dynamic)
|
|
166
|
+
ifAnyDep('vitest', vitestConfig, []),
|
|
278
167
|
|
|
279
168
|
// Prettier plugin is responsible for running prettier as an ESLint
|
|
280
169
|
// rule and turning off ESLint rules that might conflict.
|
|
281
170
|
// IMPORTANT: KEEP THIS LAST TO OVERRIDE ESLINT!
|
|
282
|
-
|
|
283
|
-
files: ['**/*.{js,ts,jsx,tsx,md,yml,yaml,html,json,jsonc,json5}'],
|
|
284
|
-
|
|
285
|
-
extends: [prettierConfig],
|
|
171
|
+
prettier,
|
|
286
172
|
|
|
173
|
+
{
|
|
287
174
|
rules: {
|
|
288
|
-
// Reset prettier rule passing in
|
|
175
|
+
// Reset prettier rule passing in codfish's prettier config.
|
|
176
|
+
// IMPORTANT: KEEP THIS LAST TO OVERRIDE PRETTIER PLUGIN!
|
|
289
177
|
'prettier/prettier': useBuiltinPrettierConfig ? ['error', prettierBuiltInConfig] : 'error',
|
|
290
178
|
},
|
|
291
179
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codfish/eslint-config",
|
|
3
|
-
"version": "0.0.0-PR-
|
|
3
|
+
"version": "0.0.0-PR-125--8d3b55f",
|
|
4
4
|
"description": "Modern ESLint configuration with TypeScript, React, and testing framework support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -45,54 +45,43 @@
|
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsc --emitDeclarationOnly",
|
|
47
47
|
"dev": "tsc --watch",
|
|
48
|
-
"
|
|
49
|
-
"lint": "eslint",
|
|
50
|
-
"
|
|
51
|
-
"test": "vitest",
|
|
52
|
-
"test:coverage": "vitest --coverage",
|
|
48
|
+
"type-check": "tsc --noEmit",
|
|
49
|
+
"lint": "eslint .",
|
|
50
|
+
"fix": "prettier --write \"**/*.{json,css,scss,md}\" --config ./prettier.js && npm run lint -- --fix",
|
|
53
51
|
"prepublishOnly": "npm run build",
|
|
54
52
|
"prepare": "husky"
|
|
55
53
|
},
|
|
56
54
|
"dependencies": {
|
|
57
|
-
"@commitlint/cli": "^
|
|
58
|
-
"@commitlint/config-conventional": "^
|
|
59
|
-
"@eslint/js": "^
|
|
60
|
-
"@eslint
|
|
61
|
-
"@eslint/markdown": "^8.0.0",
|
|
62
|
-
"@html-eslint/eslint-plugin": "^0.58.0",
|
|
63
|
-
"@html-eslint/parser": "^0.58.0",
|
|
64
|
-
"@next/eslint-plugin-next": "^16.1.6",
|
|
65
|
-
"@tanstack/eslint-plugin-query": "^5.91.4",
|
|
66
|
-
"@vitest/eslint-plugin": "^1.6.9",
|
|
55
|
+
"@commitlint/cli": "^19.8.1",
|
|
56
|
+
"@commitlint/config-conventional": "^19.8.1",
|
|
57
|
+
"@eslint/js": "^9.35.0",
|
|
58
|
+
"@vitest/eslint-plugin": "^1.3.10",
|
|
67
59
|
"cosmiconfig": "^9.0.0",
|
|
68
60
|
"eslint-config-prettier": "^10.1.8",
|
|
69
|
-
"eslint-plugin-jest": "^29.
|
|
61
|
+
"eslint-plugin-jest": "^29.0.1",
|
|
70
62
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
71
|
-
"eslint-plugin-prettier": "^5.5.
|
|
63
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
72
64
|
"eslint-plugin-react": "^7.37.5",
|
|
73
|
-
"eslint-plugin-react-hooks": "^
|
|
74
|
-
"eslint-plugin-react-refresh": "^0.5.2",
|
|
65
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
75
66
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
76
|
-
"eslint-plugin-testing-library": "^7.
|
|
77
|
-
"eslint-plugin-yml": "^
|
|
78
|
-
"
|
|
67
|
+
"eslint-plugin-testing-library": "^7.1.0",
|
|
68
|
+
"eslint-plugin-yml": "^1.16.0",
|
|
69
|
+
"@next/eslint-plugin-next": "^15.1.6",
|
|
70
|
+
"globals": "^16.4.0",
|
|
79
71
|
"lodash.has": "^4.5.2",
|
|
80
|
-
"prettier": "
|
|
81
|
-
"read-package-up": "^
|
|
82
|
-
"typescript-eslint": "^8.
|
|
72
|
+
"prettier": "^3.6.2",
|
|
73
|
+
"read-package-up": "^11.0.0",
|
|
74
|
+
"typescript-eslint": "^8.44.0"
|
|
83
75
|
},
|
|
84
76
|
"devDependencies": {
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"doctoc": "^2.3.0",
|
|
88
|
-
"eslint": "^10.0.2",
|
|
77
|
+
"doctoc": "^2.2.1",
|
|
78
|
+
"eslint": "^9.35.0",
|
|
89
79
|
"husky": "^9.1.7",
|
|
90
|
-
"lint-staged": "^
|
|
91
|
-
"typescript": "^
|
|
92
|
-
"vitest": "^4.0.18"
|
|
80
|
+
"lint-staged": "^16.1.6",
|
|
81
|
+
"typescript": "^5.9.2"
|
|
93
82
|
},
|
|
94
83
|
"engines": {
|
|
95
|
-
"node": ">=20.
|
|
84
|
+
"node": ">=20.0.0"
|
|
96
85
|
},
|
|
97
86
|
"files": [
|
|
98
87
|
"dist",
|
|
@@ -105,11 +94,10 @@
|
|
|
105
94
|
"commitlint.js"
|
|
106
95
|
],
|
|
107
96
|
"peerDependencies": {
|
|
108
|
-
"eslint": ">=
|
|
109
|
-
"prettier": ">= 3"
|
|
97
|
+
"eslint": ">= 9"
|
|
110
98
|
},
|
|
111
99
|
"peerDependenciesMeta": {
|
|
112
|
-
"
|
|
100
|
+
"typescript": {
|
|
113
101
|
"optional": true
|
|
114
102
|
}
|
|
115
103
|
},
|
|
@@ -128,6 +116,6 @@
|
|
|
128
116
|
]
|
|
129
117
|
},
|
|
130
118
|
"volta": {
|
|
131
|
-
"node": "24.
|
|
119
|
+
"node": "24.8.0"
|
|
132
120
|
}
|
|
133
121
|
}
|
package/rules/jest.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defineConfig } from 'eslint/config';
|
|
2
|
+
import jest from 'eslint-plugin-jest';
|
|
3
|
+
import testingLibrary from 'eslint-plugin-testing-library';
|
|
4
|
+
|
|
5
|
+
import { ifAnyDep } from '../utils.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Jest ESLint configuration for flat config format
|
|
9
|
+
* Includes Jest-specific rules, globals, and Testing Library rules for test files
|
|
10
|
+
*/
|
|
11
|
+
export default defineConfig([
|
|
12
|
+
{
|
|
13
|
+
name: 'codfish/jest',
|
|
14
|
+
|
|
15
|
+
files: [
|
|
16
|
+
'**/__tests__/**/*.{js,ts,jsx,tsx}',
|
|
17
|
+
'**/*.{test,spec}.{js,ts,jsx,tsx}',
|
|
18
|
+
'**/jest.config.{js,ts}',
|
|
19
|
+
'**/jest.setup.{js,ts}',
|
|
20
|
+
'**/setupTests.{js,ts}',
|
|
21
|
+
'**/testUtils.{js,ts}',
|
|
22
|
+
'tests/**/*.{js,ts,jsx,tsx}',
|
|
23
|
+
],
|
|
24
|
+
|
|
25
|
+
...jest.configs['flat/recommended'],
|
|
26
|
+
|
|
27
|
+
...ifAnyDep('react-testing-library', testingLibrary.configs['flat/react'], {}),
|
|
28
|
+
...ifAnyDep('vue-testing-library', testingLibrary.configs['flat/vue'], {}),
|
|
29
|
+
|
|
30
|
+
rules: {
|
|
31
|
+
'no-console': 'off',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
]);
|
package/rules/react.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import nextPlugin from '@next/eslint-plugin-next';
|
|
2
|
-
import tanstackQuery from '@tanstack/eslint-plugin-query';
|
|
3
2
|
import { defineConfig } from 'eslint/config';
|
|
4
3
|
import jsxA11y from 'eslint-plugin-jsx-a11y';
|
|
5
4
|
import react from 'eslint-plugin-react';
|
|
6
5
|
import reactHooks from 'eslint-plugin-react-hooks';
|
|
7
|
-
import reactRefresh from 'eslint-plugin-react-refresh';
|
|
8
6
|
import globals from 'globals';
|
|
9
7
|
|
|
10
|
-
import {
|
|
8
|
+
import { ifAnyDep } from '../utils.js';
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* React ESLint configuration. Includes React, React Hooks, and JSX accessibility rules.
|
|
@@ -20,17 +18,10 @@ export default defineConfig([
|
|
|
20
18
|
{
|
|
21
19
|
name: 'codfish/react',
|
|
22
20
|
|
|
23
|
-
files: ['**/*.jsx
|
|
21
|
+
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
reactHooks.configs.flat['recommended-latest'],
|
|
28
|
-
reactRefresh.configs.recommended,
|
|
29
|
-
jsxA11y.flatConfigs.recommended,
|
|
30
|
-
ifAnyDep('@tanstack/react-query', tanstackQuery.configs['flat/recommended']),
|
|
31
|
-
ifAnyDep('next', nextPlugin.configs.recommended),
|
|
32
|
-
ifAnyDep('next', nextPlugin.configs['core-web-vitals']),
|
|
33
|
-
].filter(Boolean),
|
|
23
|
+
...react.configs.flat.recommended,
|
|
24
|
+
...jsxA11y.flatConfigs.recommended,
|
|
34
25
|
|
|
35
26
|
languageOptions: {
|
|
36
27
|
globals: {
|
|
@@ -38,49 +29,26 @@ export default defineConfig([
|
|
|
38
29
|
...globals.browser,
|
|
39
30
|
},
|
|
40
31
|
},
|
|
32
|
+
},
|
|
41
33
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// Avoid 'detect' — it uses context.getFilename() which was removed in ESLint 10.
|
|
45
|
-
// Read the major version from the consumer's package.json instead.
|
|
46
|
-
version: getDepVersion('react') || 'detect',
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
rules: {
|
|
51
|
-
// React 17+ uses automatic JSX runtime, no need to import React
|
|
52
|
-
'react/react-in-jsx-scope': 'off',
|
|
53
|
-
'react/jsx-uses-react': 'off',
|
|
54
|
-
|
|
55
|
-
// TypeScript provides type checking, no need for PropTypes
|
|
56
|
-
'react/prop-types': 'off',
|
|
57
|
-
|
|
58
|
-
// this rule is too noisey and doesn't account for certain valid use cases
|
|
59
|
-
'react-hooks/exhaustive-deps': 'off',
|
|
60
|
-
|
|
61
|
-
// sometimes autoFocus is needed for better UX. @todo - revisit later?
|
|
62
|
-
'jsx-a11y/no-autofocus': 'off',
|
|
63
|
-
|
|
64
|
-
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
|
|
34
|
+
// React Hooks configuration
|
|
35
|
+
reactHooks.configs['recommended-latest'],
|
|
65
36
|
|
|
66
|
-
|
|
37
|
+
// Next.js configuration (dynamic)
|
|
38
|
+
ifAnyDep(
|
|
39
|
+
'next',
|
|
40
|
+
{
|
|
41
|
+
...nextPlugin.flatConfig.recommended,
|
|
42
|
+
...nextPlugin.flatConfig.coreWebVitals,
|
|
67
43
|
|
|
68
|
-
|
|
69
|
-
'next',
|
|
70
|
-
{
|
|
71
|
-
// annoying cause this is common in Next.js, i.e. generateMetadata()
|
|
72
|
-
'react-refresh/only-export-components': ['off'],
|
|
73
|
-
},
|
|
74
|
-
{},
|
|
75
|
-
),
|
|
44
|
+
name: 'codfish/next',
|
|
76
45
|
},
|
|
77
|
-
|
|
46
|
+
{},
|
|
47
|
+
),
|
|
78
48
|
|
|
79
49
|
{
|
|
80
|
-
name: 'codfish/react-next-config',
|
|
81
|
-
files: ['next.config.js', 'next.config.ts'],
|
|
82
50
|
rules: {
|
|
83
|
-
'
|
|
51
|
+
'react-hooks/exhaustive-deps': 'off',
|
|
84
52
|
},
|
|
85
53
|
},
|
|
86
54
|
]);
|
package/rules/vitest.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import vitest from '@vitest/eslint-plugin';
|
|
2
|
+
import { defineConfig } from 'eslint/config';
|
|
3
|
+
import testingLibrary from 'eslint-plugin-testing-library';
|
|
4
|
+
import globals from 'globals';
|
|
5
|
+
|
|
6
|
+
import { ifAnyDep } from '../utils.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Vitest ESLint configuration for flat config format
|
|
10
|
+
* Includes Vitest-specific rules, globals, and Testing Library rules for test files
|
|
11
|
+
*/
|
|
12
|
+
export default defineConfig([
|
|
13
|
+
{
|
|
14
|
+
files: [
|
|
15
|
+
'**/*.{spec,test}.{js,ts,jsx,tsx}',
|
|
16
|
+
'**/tests/**/*.{js,ts,jsx,tsx}',
|
|
17
|
+
'**/__mocks__/**/*.{js,ts,jsx,tsx}',
|
|
18
|
+
'**/__tests__/**/*.{js,ts,jsx,tsx}',
|
|
19
|
+
],
|
|
20
|
+
|
|
21
|
+
...vitest.configs.recommended,
|
|
22
|
+
|
|
23
|
+
...ifAnyDep('react-testing-library', testingLibrary.configs['flat/react'], {}),
|
|
24
|
+
...ifAnyDep('vue-testing-library', testingLibrary.configs['flat/vue'], {}),
|
|
25
|
+
|
|
26
|
+
name: 'codfish/vitest',
|
|
27
|
+
|
|
28
|
+
languageOptions: {
|
|
29
|
+
globals: {
|
|
30
|
+
...vitest.environments.env.globals,
|
|
31
|
+
...globals.node,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
rules: {
|
|
36
|
+
'no-console': 'off',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
]);
|
package/utils.js
CHANGED
|
@@ -8,9 +8,12 @@
|
|
|
8
8
|
import fs from 'node:fs';
|
|
9
9
|
import { cosmiconfigSync } from 'cosmiconfig';
|
|
10
10
|
import has from 'lodash.has';
|
|
11
|
-
import {
|
|
11
|
+
import { readPackageUp } from 'read-package-up';
|
|
12
12
|
|
|
13
|
-
const { packageJson: pkg, path: pkgPath } =
|
|
13
|
+
const { packageJson: pkg, path: pkgPath } =
|
|
14
|
+
(await readPackageUp({
|
|
15
|
+
cwd: fs.realpathSync(process.cwd()),
|
|
16
|
+
})) || {};
|
|
14
17
|
|
|
15
18
|
const hasPkgProp = props => [props].flat().some(prop => has(pkg, prop));
|
|
16
19
|
const hasPkgSubProp = pkgProp => props => hasPkgProp([props].flat().map(p => `${pkgProp}.${p}`));
|
|
@@ -23,17 +26,6 @@ export const hasAnyDep = args => [hasDep, hasDevDep, hasPeerDep].some(fn => fn(a
|
|
|
23
26
|
|
|
24
27
|
export const ifAnyDep = (deps, t, f) => (hasAnyDep([deps].flat()) ? t : f);
|
|
25
28
|
|
|
26
|
-
/**
|
|
27
|
-
* Get the version of a dependency from the consumer's package.json.
|
|
28
|
-
* Returns the major version as a string (e.g. '18', '19'), or null if not found.
|
|
29
|
-
*/
|
|
30
|
-
export function getDepVersion(dep) {
|
|
31
|
-
const spec = pkg?.dependencies?.[dep] || pkg?.devDependencies?.[dep] || pkg?.peerDependencies?.[dep];
|
|
32
|
-
if (!spec) return null;
|
|
33
|
-
const match = spec.match(/\d+/);
|
|
34
|
-
return match ? match[0] : null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
29
|
export function hasLocalConfig(moduleName, searchOptions = {}) {
|
|
38
30
|
const explorerSync = cosmiconfigSync(moduleName, searchOptions);
|
|
39
31
|
const result = explorerSync.search(pkgPath || './');
|
package/dist/rules/tests.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tests.d.ts","sourceRoot":"","sources":["../../rules/tests.js"],"names":[],"mappings":""}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export default tseslintConfig;
|
|
2
|
-
export const rules: {
|
|
3
|
-
'@typescript-eslint/no-unused-vars': (string | {
|
|
4
|
-
ignoreRestSiblings: boolean;
|
|
5
|
-
})[];
|
|
6
|
-
'@typescript-eslint/no-empty-function': string;
|
|
7
|
-
'@typescript-eslint/naming-convention': (string | {
|
|
8
|
-
selector: string[];
|
|
9
|
-
format: string[];
|
|
10
|
-
custom: {
|
|
11
|
-
regex: string;
|
|
12
|
-
match: boolean;
|
|
13
|
-
};
|
|
14
|
-
})[];
|
|
15
|
-
'@typescript-eslint/ban-ts-comment': (string | {
|
|
16
|
-
'ts-ignore': string;
|
|
17
|
-
'ts-expect-error': string;
|
|
18
|
-
'ts-nocheck': string;
|
|
19
|
-
})[];
|
|
20
|
-
'@typescript-eslint/no-restricted-types': (string | {
|
|
21
|
-
types: {
|
|
22
|
-
'React.FC': {
|
|
23
|
-
message: string;
|
|
24
|
-
};
|
|
25
|
-
'React.FunctionComponent': {
|
|
26
|
-
message: string;
|
|
27
|
-
};
|
|
28
|
-
};
|
|
29
|
-
})[];
|
|
30
|
-
} | {
|
|
31
|
-
'@typescript-eslint/no-unused-vars'?: never;
|
|
32
|
-
'@typescript-eslint/no-empty-function'?: never;
|
|
33
|
-
'@typescript-eslint/naming-convention'?: never;
|
|
34
|
-
'@typescript-eslint/ban-ts-comment'?: never;
|
|
35
|
-
'@typescript-eslint/no-restricted-types'?: never;
|
|
36
|
-
};
|
|
37
|
-
declare const tseslintConfig: import("eslint").Linter.Config[];
|
|
38
|
-
//# sourceMappingURL=typescript.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../rules/typescript.js"],"names":[],"mappings":";AAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwCO;AA9CP,8BACa,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CACsC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"eslint-execution.spec.d.ts","sourceRoot":"","sources":["../../../tests/integration/eslint-execution.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"react-integration.spec.d.ts","sourceRoot":"","sources":["../../../tests/integration/react-integration.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rule-application.spec.d.ts","sourceRoot":"","sources":["../../../tests/integration/rule-application.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"edge-cases.spec.d.ts","sourceRoot":"","sources":["../../../tests/scenarios/edge-cases.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-loading.spec.d.ts","sourceRoot":"","sources":["../../../tests/unit/config-loading.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-detection.spec.d.ts","sourceRoot":"","sources":["../../../tests/unit/dynamic-detection.spec.js"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.spec.d.ts","sourceRoot":"","sources":["../../../tests/unit/utils.spec.js"],"names":[],"mappings":""}
|
package/dist/vitest.config.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.config.d.ts","sourceRoot":"","sources":["../vitest.config.js"],"names":[],"mappings":""}
|
package/rules/tests.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import vitest from '@vitest/eslint-plugin';
|
|
2
|
-
import { defineConfig } from 'eslint/config';
|
|
3
|
-
import jest from 'eslint-plugin-jest';
|
|
4
|
-
import testingLibrary from 'eslint-plugin-testing-library';
|
|
5
|
-
import globals from 'globals';
|
|
6
|
-
|
|
7
|
-
import { ifAnyDep } from '../utils.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Jest ESLint configuration for flat config format
|
|
11
|
-
* Includes Jest-specific rules, globals, and Testing Library rules for test files
|
|
12
|
-
*/
|
|
13
|
-
export default defineConfig({
|
|
14
|
-
name: 'codfish/tests',
|
|
15
|
-
|
|
16
|
-
files: [
|
|
17
|
-
'**/*.{spec,test}.{js,ts,jsx,tsx}',
|
|
18
|
-
'**/tests/**/*.{js,ts,jsx,tsx}',
|
|
19
|
-
'**/__mocks__/**/*.{js,ts,jsx,tsx}',
|
|
20
|
-
'**/__tests__/**/*.{js,ts,jsx,tsx}',
|
|
21
|
-
'**/jest.config.{js,ts}',
|
|
22
|
-
'**/jest.setup.{js,ts}',
|
|
23
|
-
'**/vitest.config.{js,ts}',
|
|
24
|
-
'**/vitest.setup.{js,ts}',
|
|
25
|
-
'**/setupTests.{js,ts}',
|
|
26
|
-
'**/testUtils.{js,ts}',
|
|
27
|
-
'tests/**/*.{js,ts,jsx,tsx}',
|
|
28
|
-
],
|
|
29
|
-
|
|
30
|
-
extends: [
|
|
31
|
-
ifAnyDep('jest', jest.configs['flat/recommended'], false),
|
|
32
|
-
ifAnyDep('vitest', vitest.configs.recommended, false),
|
|
33
|
-
ifAnyDep('@testing-library/dom', testingLibrary.configs['flat/dom'], false),
|
|
34
|
-
ifAnyDep('@testing-library/react', testingLibrary.configs['flat/react'], false),
|
|
35
|
-
ifAnyDep('@testing-library/vue', testingLibrary.configs['flat/vue'], false),
|
|
36
|
-
ifAnyDep('@testing-library/svelte', testingLibrary.configs['flat/svelte'], false),
|
|
37
|
-
ifAnyDep('@testing-library/angular', testingLibrary.configs['flat/angular'], false),
|
|
38
|
-
ifAnyDep('@testing-library/marko', testingLibrary.configs['flat/marko'], false),
|
|
39
|
-
].filter(Boolean),
|
|
40
|
-
|
|
41
|
-
languageOptions: {
|
|
42
|
-
globals: {
|
|
43
|
-
...globals.node,
|
|
44
|
-
...ifAnyDep('jest', globals.jest, {}),
|
|
45
|
-
...ifAnyDep('vitest', globals.vitest, {}),
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
rules: {
|
|
50
|
-
'no-console': 'off',
|
|
51
|
-
},
|
|
52
|
-
});
|
package/rules/typescript.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { hasAnyDep } from '../utils.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* TypeScript ESLint configuration. Dynamically loads typescript-eslint
|
|
5
|
-
* only when typescript is installed in the consuming project.
|
|
6
|
-
*
|
|
7
|
-
* - https://typescript-eslint.io/
|
|
8
|
-
*/
|
|
9
|
-
const hasTypeScript = hasAnyDep('typescript');
|
|
10
|
-
const tseslintConfig =
|
|
11
|
-
/** @type {import('eslint').Linter.Config[]} */
|
|
12
|
-
(hasTypeScript ? [(await import('typescript-eslint')).configs.recommended] : []);
|
|
13
|
-
|
|
14
|
-
export default tseslintConfig;
|
|
15
|
-
|
|
16
|
-
export const rules = hasTypeScript
|
|
17
|
-
? {
|
|
18
|
-
// Allows destructuring of rest properties even if they are unused
|
|
19
|
-
'@typescript-eslint/no-unused-vars': ['error', { ignoreRestSiblings: true }],
|
|
20
|
-
'@typescript-eslint/no-empty-function': 'off',
|
|
21
|
-
'@typescript-eslint/naming-convention': [
|
|
22
|
-
'error',
|
|
23
|
-
{
|
|
24
|
-
selector: ['interface', 'typeAlias'],
|
|
25
|
-
format: ['PascalCase'],
|
|
26
|
-
custom: {
|
|
27
|
-
regex: '^I[A-Z]', // prevent prefixing interfaces and type alias declarations with "I"
|
|
28
|
-
match: false,
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
'@typescript-eslint/ban-ts-comment': [
|
|
33
|
-
'error',
|
|
34
|
-
{
|
|
35
|
-
// If you need to use a ts comment, make sure you have a description.
|
|
36
|
-
'ts-ignore': 'allow-with-description',
|
|
37
|
-
'ts-expect-error': 'allow-with-description',
|
|
38
|
-
'ts-nocheck': 'allow-with-description',
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
|
|
42
|
-
'@typescript-eslint/no-restricted-types': [
|
|
43
|
-
'error',
|
|
44
|
-
{
|
|
45
|
-
types: {
|
|
46
|
-
'React.FC': {
|
|
47
|
-
message: 'Useless and has some drawbacks, see https://github.com/facebook/create-react-app/pull/8177',
|
|
48
|
-
},
|
|
49
|
-
'React.FunctionComponent': {
|
|
50
|
-
message: 'Useless and has some drawbacks, see https://github.com/facebook/create-react-app/pull/8177',
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
}
|
|
56
|
-
: {};
|