eslint-config-axkit 1.4.0 → 1.6.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/README.md +9 -7
- package/dist/index.d.ts +14 -1
- package/dist/index.js +46 -5
- package/dist/node-test-config.d.ts +8 -0
- package/dist/node-test-config.js +27 -0
- package/dist/vitest-config.d.ts +14 -1
- package/dist/vitest-config.js +63 -62
- package/package.json +14 -11
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# eslint-config-axkit
|
|
2
2
|
|
|
3
|
-
Reusable ESLint flat config for TypeScript + Node.js projects with strict type checking, Prettier,
|
|
3
|
+
Reusable ESLint flat config for TypeScript + Node.js projects with strict type checking, Prettier, and Unicorn.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
@@ -83,12 +83,14 @@ export default [
|
|
|
83
83
|
|
|
84
84
|
## Options
|
|
85
85
|
|
|
86
|
-
| Option | Type | Description
|
|
87
|
-
| --------------- | --------- |
|
|
88
|
-
| `gitignorePath` | `string` | Path to `.gitignore` file. Patterns will be added to ESLint's ignore list.
|
|
89
|
-
| `
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
86
|
+
| Option | Type | Description |
|
|
87
|
+
| --------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
88
|
+
| `gitignorePath` | `string` | Path to `.gitignore` file. Patterns will be added to ESLint's ignore list. |
|
|
89
|
+
| `vitest` | `boolean` | Enable Vitest ESLint rules for test files. Requires `@vitest/eslint-plugin` to be installed. |
|
|
90
|
+
| `fastify` | `boolean` | Relax rules that conflict with idiomatic Fastify patterns. Configures `unicorn/prevent-abbreviations` with an allowList for common terms (`app`, `db`, `req`, etc.) and disables `@typescript-eslint/require-await` and `@typescript-eslint/strict-void-return`. |
|
|
91
|
+
| `nextjs` | `boolean` | Enable Next.js rules (`eslint-config-next` core-web-vitals + typescript). Requires `eslint-config-next` to be installed. |
|
|
92
|
+
| `storybook` | `boolean` | Enable Storybook rules (`eslint-plugin-storybook` flat/recommended). Requires `eslint-plugin-storybook` to be installed. |
|
|
93
|
+
| `tailwindcss` | `string` | Path to the Tailwind CSS entry point (e.g. `"src/app/globals.css"`). Enables `eslint-plugin-better-tailwindcss` recommended rules enforcing stylistic and correctness rules. Requires `eslint-plugin-better-tailwindcss` to be installed. |
|
|
92
94
|
|
|
93
95
|
## Requirements
|
|
94
96
|
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,18 @@ export type Options = {
|
|
|
11
11
|
* Requires `eslint-config-next` to be installed.
|
|
12
12
|
*/
|
|
13
13
|
nextjs?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Enable Vitest ESLint rules for test files.
|
|
16
|
+
* Requires `@vitest/eslint-plugin` to be installed.
|
|
17
|
+
*/
|
|
18
|
+
vitest?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Relax rules that conflict with idiomatic Fastify patterns:
|
|
21
|
+
* - `unicorn/prevent-abbreviations` — configured with allowList for common Fastify terms (`app`, `db`, `req`, `res`, `opts`, `params`, etc.)
|
|
22
|
+
* - `@typescript-eslint/require-await` — disabled; `FastifyPluginAsync` requires `async` but plugin bodies often contain no `await`
|
|
23
|
+
* - `@typescript-eslint/strict-void-return` — disabled; route handlers use `return reply.notFound()` as control flow
|
|
24
|
+
*/
|
|
25
|
+
fastify?: boolean;
|
|
14
26
|
/**
|
|
15
27
|
* Enable Storybook rules (eslint-plugin-storybook flat/recommended).
|
|
16
28
|
* Requires `eslint-plugin-storybook` to be installed.
|
|
@@ -31,10 +43,11 @@ export type Options = {
|
|
|
31
43
|
* - ESLint recommended rules
|
|
32
44
|
* - TypeScript strict type checking
|
|
33
45
|
* - Unicorn plugin (recommended)
|
|
34
|
-
* -
|
|
46
|
+
* - `node:test` support (`allowForKnownSafeCalls` for promise-returning functions)
|
|
35
47
|
* - Prettier compatibility (disables conflicting rules)
|
|
36
48
|
*
|
|
37
49
|
* Optional:
|
|
50
|
+
* - Vitest plugin for test files via `vitest: true`
|
|
38
51
|
* - Next.js rules (core-web-vitals + typescript) via `nextjs: true`
|
|
39
52
|
* - Storybook rules (flat/recommended) via `storybook: true`
|
|
40
53
|
* - Tailwind CSS rules (better-tailwindcss/recommended) via `tailwindcss: "path/to/entry.css"`
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,8 @@ import eslintConfigPrettier from "eslint-config-prettier/flat";
|
|
|
5
5
|
import eslintPluginUnicorn from "eslint-plugin-unicorn";
|
|
6
6
|
import { importOptional } from "./import-optional.js";
|
|
7
7
|
import { baseConfig } from "./base-config.js";
|
|
8
|
-
import {
|
|
8
|
+
import { nodeTestConfig } from "./node-test-config.js";
|
|
9
|
+
import { createVitestConfig } from "./vitest-config.js";
|
|
9
10
|
/**
|
|
10
11
|
* Creates a complete ESLint flat config for TypeScript projects.
|
|
11
12
|
*
|
|
@@ -13,17 +14,23 @@ import { vitestConfig } from "./vitest-config.js";
|
|
|
13
14
|
* - ESLint recommended rules
|
|
14
15
|
* - TypeScript strict type checking
|
|
15
16
|
* - Unicorn plugin (recommended)
|
|
16
|
-
* -
|
|
17
|
+
* - `node:test` support (`allowForKnownSafeCalls` for promise-returning functions)
|
|
17
18
|
* - Prettier compatibility (disables conflicting rules)
|
|
18
19
|
*
|
|
19
20
|
* Optional:
|
|
21
|
+
* - Vitest plugin for test files via `vitest: true`
|
|
20
22
|
* - Next.js rules (core-web-vitals + typescript) via `nextjs: true`
|
|
21
23
|
* - Storybook rules (flat/recommended) via `storybook: true`
|
|
22
24
|
* - Tailwind CSS rules (better-tailwindcss/recommended) via `tailwindcss: "path/to/entry.css"`
|
|
23
25
|
*/
|
|
24
26
|
export async function axkit(options = {}) {
|
|
25
|
-
const { gitignorePath, nextjs, storybook, tailwindcss } = options;
|
|
26
|
-
const configs = [
|
|
27
|
+
const { gitignorePath, vitest, fastify, nextjs, storybook, tailwindcss } = options;
|
|
28
|
+
const configs = [
|
|
29
|
+
{
|
|
30
|
+
name: "axkit/ignores",
|
|
31
|
+
ignores: [".agents/", ".claude/"],
|
|
32
|
+
},
|
|
33
|
+
];
|
|
27
34
|
// ── Gitignore ──────────────────────────────────────────────────────
|
|
28
35
|
if (gitignorePath) {
|
|
29
36
|
configs.push(includeIgnoreFile(gitignorePath, "Copy patterns from .gitignore"));
|
|
@@ -53,7 +60,41 @@ export async function axkit(options = {}) {
|
|
|
53
60
|
name: "axkit/config-files",
|
|
54
61
|
files: ["*.config.{js,ts,mjs,mts}"],
|
|
55
62
|
...tseslint.configs.disableTypeChecked,
|
|
56
|
-
},
|
|
63
|
+
},
|
|
64
|
+
// node:test (always applied — harmless if not using node:test)
|
|
65
|
+
nodeTestConfig);
|
|
66
|
+
// ── Vitest (optional, requires @vitest/eslint-plugin) ──────────────
|
|
67
|
+
if (vitest) {
|
|
68
|
+
const vitestPlugin = await importOptional("@vitest/eslint-plugin");
|
|
69
|
+
configs.push(createVitestConfig(vitestPlugin));
|
|
70
|
+
}
|
|
71
|
+
// ── Fastify (disable conflicting rules) ────────────────────────────
|
|
72
|
+
if (fastify) {
|
|
73
|
+
configs.push({
|
|
74
|
+
name: "axkit/fastify",
|
|
75
|
+
rules: {
|
|
76
|
+
"unicorn/prevent-abbreviations": [
|
|
77
|
+
"error",
|
|
78
|
+
{
|
|
79
|
+
allowList: {
|
|
80
|
+
app: true,
|
|
81
|
+
args: true,
|
|
82
|
+
ctx: true,
|
|
83
|
+
db: true,
|
|
84
|
+
env: true,
|
|
85
|
+
err: true,
|
|
86
|
+
opts: true,
|
|
87
|
+
params: true,
|
|
88
|
+
req: true,
|
|
89
|
+
res: true,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
"@typescript-eslint/require-await": "off",
|
|
94
|
+
"@typescript-eslint/strict-void-return": "off",
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
57
98
|
// ── Storybook (after base, before Prettier) ────────────────────────
|
|
58
99
|
if (storybook) {
|
|
59
100
|
const storybookPlugin = (await importOptional("eslint-plugin-storybook"));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Linter } from "eslint";
|
|
2
|
+
/**
|
|
3
|
+
* Whitelists promise-returning `node:test` functions in the
|
|
4
|
+
* `no-floating-promises` rule via `allowForKnownSafeCalls`.
|
|
5
|
+
*
|
|
6
|
+
* Always applied — harmless if not using `node:test`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const nodeTestConfig: Linter.Config;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whitelists promise-returning `node:test` functions in the
|
|
3
|
+
* `no-floating-promises` rule via `allowForKnownSafeCalls`.
|
|
4
|
+
*
|
|
5
|
+
* Always applied — harmless if not using `node:test`.
|
|
6
|
+
*/
|
|
7
|
+
export const nodeTestConfig = {
|
|
8
|
+
name: "axkit/node-test",
|
|
9
|
+
files: [
|
|
10
|
+
"**/*.{test,spec}.{ts,tsx,js,mjs,cjs,mts,cts}",
|
|
11
|
+
"tests/**/*.{ts,tsx,js,mjs,cjs,mts,cts}",
|
|
12
|
+
],
|
|
13
|
+
rules: {
|
|
14
|
+
"@typescript-eslint/no-floating-promises": [
|
|
15
|
+
"error",
|
|
16
|
+
{
|
|
17
|
+
allowForKnownSafeCalls: [
|
|
18
|
+
{
|
|
19
|
+
from: "package",
|
|
20
|
+
package: "node:test",
|
|
21
|
+
name: ["describe", "it", "test", "suite", "todo", "skip", "only"],
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
};
|
package/dist/vitest-config.d.ts
CHANGED
|
@@ -1,2 +1,15 @@
|
|
|
1
1
|
import type { Linter } from "eslint";
|
|
2
|
-
|
|
2
|
+
type VitestPlugin = {
|
|
3
|
+
configs: {
|
|
4
|
+
recommended: {
|
|
5
|
+
rules: Linter.RulesRecord;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
environments: {
|
|
9
|
+
env: {
|
|
10
|
+
globals: Record<string, boolean>;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export declare function createVitestConfig(vitest: VitestPlugin): Linter.Config;
|
|
15
|
+
export {};
|
package/dist/vitest-config.js
CHANGED
|
@@ -1,62 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
};
|
|
1
|
+
export function createVitestConfig(vitest) {
|
|
2
|
+
return {
|
|
3
|
+
name: "axkit/vitest",
|
|
4
|
+
files: [
|
|
5
|
+
"**/*.{test,spec}.{ts,tsx,js,mjs,cjs,mts,cts}",
|
|
6
|
+
"tests/**/*.{ts,tsx,js,mjs,cjs,mts,cts}",
|
|
7
|
+
],
|
|
8
|
+
plugins: { vitest },
|
|
9
|
+
rules: {
|
|
10
|
+
...vitest.configs.recommended.rules,
|
|
11
|
+
// Ensure expect.poll() and expect.element() are awaited
|
|
12
|
+
"vitest/require-awaited-expect-poll": "error",
|
|
13
|
+
// Keep vi.mock() and other hoisted APIs at the top of files
|
|
14
|
+
"vitest/hoisted-apis-on-top": "warn",
|
|
15
|
+
// Prefer toHaveBeenCalledTimes() matcher
|
|
16
|
+
"vitest/prefer-to-have-been-called-times": "warn",
|
|
17
|
+
// Prefer mockResolvedValue() over mockImplementation(() => Promise.resolve())
|
|
18
|
+
"vitest/prefer-mock-promise-shorthand": "warn",
|
|
19
|
+
// Prefer expectTypeOf() for type testing
|
|
20
|
+
"vitest/prefer-expect-type-of": "warn",
|
|
21
|
+
// Enforce consistent use of .each vs .for for parameterized tests
|
|
22
|
+
"vitest/consistent-each-for": "warn",
|
|
23
|
+
// Keep hooks (beforeEach, afterEach, etc.) at the top of describe blocks
|
|
24
|
+
"vitest/prefer-hooks-on-top": "warn",
|
|
25
|
+
// ===== Test Logic Errors =====
|
|
26
|
+
// No conditionals (if/else) inside test bodies - tests should be deterministic
|
|
27
|
+
"vitest/no-conditional-in-test": "error",
|
|
28
|
+
// No conditionally defined tests - tests should always run
|
|
29
|
+
"vitest/no-conditional-tests": "error",
|
|
30
|
+
// No return statements in tests - just execute assertions
|
|
31
|
+
"vitest/no-test-return-statement": "warn",
|
|
32
|
+
// No duplicate lifecycle hooks
|
|
33
|
+
"vitest/no-duplicate-hooks": "warn",
|
|
34
|
+
// ===== Better Matchers (auto-fixable) =====
|
|
35
|
+
// Use toBe() for primitives (strict equality)
|
|
36
|
+
"vitest/prefer-to-be": "warn",
|
|
37
|
+
// Use toHaveLength() instead of expect(arr.length).toBe()
|
|
38
|
+
"vitest/prefer-to-have-length": "warn",
|
|
39
|
+
// Use toContain() instead of expect(arr.includes()).toBe(true)
|
|
40
|
+
"vitest/prefer-to-contain": "warn",
|
|
41
|
+
// Use toBeGreaterThan(), toBeLessThan(), etc.
|
|
42
|
+
"vitest/prefer-comparison-matcher": "warn",
|
|
43
|
+
// Use dedicated equality matchers
|
|
44
|
+
"vitest/prefer-equality-matcher": "warn",
|
|
45
|
+
// ===== Best Practices =====
|
|
46
|
+
// Use vi.spyOn() instead of direct property assignment
|
|
47
|
+
"vitest/prefer-spy-on": "warn",
|
|
48
|
+
// Use test.todo() for empty/placeholder tests
|
|
49
|
+
"vitest/prefer-todo": "warn",
|
|
50
|
+
// Use expect().resolves instead of expect(await promise)
|
|
51
|
+
"vitest/prefer-expect-resolves": "warn",
|
|
52
|
+
// No deprecated alias methods (toBeCalled → toHaveBeenCalled)
|
|
53
|
+
"vitest/no-alias-methods": "warn",
|
|
54
|
+
// Use vi.mocked() instead of type casting
|
|
55
|
+
"vitest/prefer-vi-mocked": "warn",
|
|
56
|
+
// Use .only/.skip instead of f/x prefixes
|
|
57
|
+
"vitest/no-test-prefixes": "warn",
|
|
58
|
+
},
|
|
59
|
+
languageOptions: {
|
|
60
|
+
globals: { ...vitest.environments.env.globals },
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
package/package.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"name": "eslint-config-axkit",
|
|
3
3
|
"author": "Łukasz Jerciński",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "1.
|
|
6
|
-
"description": "Reusable ESLint flat config for TypeScript + Node.js projects with strict type checking, Prettier,
|
|
5
|
+
"version": "1.6.0",
|
|
6
|
+
"description": "Reusable ESLint flat config for TypeScript + Node.js projects with strict type checking, Prettier, and Unicorn",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git+https://github.com/Jercik/eslint-config-axkit.git"
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"vitest",
|
|
54
54
|
"axkit"
|
|
55
55
|
],
|
|
56
|
-
"packageManager": "pnpm@10.30.
|
|
56
|
+
"packageManager": "pnpm@10.30.3",
|
|
57
57
|
"engines": {
|
|
58
58
|
"node": ">=22.14.0"
|
|
59
59
|
},
|
|
@@ -61,7 +61,8 @@
|
|
|
61
61
|
"eslint": ">=10",
|
|
62
62
|
"eslint-config-next": ">=16",
|
|
63
63
|
"eslint-plugin-better-tailwindcss": ">=4",
|
|
64
|
-
"eslint-plugin-storybook": ">=10"
|
|
64
|
+
"eslint-plugin-storybook": ">=10",
|
|
65
|
+
"@vitest/eslint-plugin": ">=1"
|
|
65
66
|
},
|
|
66
67
|
"peerDependenciesMeta": {
|
|
67
68
|
"eslint-config-next": {
|
|
@@ -72,25 +73,27 @@
|
|
|
72
73
|
},
|
|
73
74
|
"eslint-plugin-storybook": {
|
|
74
75
|
"optional": true
|
|
76
|
+
},
|
|
77
|
+
"@vitest/eslint-plugin": {
|
|
78
|
+
"optional": true
|
|
75
79
|
}
|
|
76
80
|
},
|
|
77
81
|
"dependencies": {
|
|
78
|
-
"@eslint/compat": "^2.0.
|
|
82
|
+
"@eslint/compat": "^2.0.3",
|
|
79
83
|
"@eslint/js": "^10.0.1",
|
|
80
|
-
"@vitest/eslint-plugin": "^1.6.9",
|
|
81
84
|
"eslint-config-prettier": "^10.1.8",
|
|
82
85
|
"eslint-plugin-unicorn": "^63.0.0",
|
|
83
|
-
"globals": "^17.
|
|
84
|
-
"typescript-eslint": "^8.56.
|
|
86
|
+
"globals": "^17.4.0",
|
|
87
|
+
"typescript-eslint": "^8.56.1"
|
|
85
88
|
},
|
|
86
89
|
"devDependencies": {
|
|
87
90
|
"@total-typescript/ts-reset": "^0.6.1",
|
|
88
|
-
"@types/node": "^25.3.
|
|
91
|
+
"@types/node": "^25.3.5",
|
|
89
92
|
"@vitest/coverage-v8": "^4.0.18",
|
|
90
|
-
"eslint": "^10.0.
|
|
93
|
+
"eslint": "^10.0.3",
|
|
91
94
|
"fta-check": "^1.5.1",
|
|
92
95
|
"fta-cli": "^3.0.0",
|
|
93
|
-
"knip": "^5.
|
|
96
|
+
"knip": "^5.85.0",
|
|
94
97
|
"prettier": "3.8.1",
|
|
95
98
|
"semantic-release": "^25.0.3",
|
|
96
99
|
"typescript": "^5.9.3",
|