@kununu/eslint-config 7.1.5 → 7.3.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 CHANGED
@@ -1,46 +1,126 @@
1
1
  # @kununu/eslint-config
2
2
 
3
- > kununu config for ESLint v9 (Flat Config)
3
+ > kununu's shared [ESLint](https://eslint.org/) config (ESLint v9 flat config)
4
4
 
5
- This package contains ESLint rules for consistent JS, JSX, TS, and TSX code across kununu's projects.
5
+ Shared linting rules for consistent JS, JSX, TS, and TSX across kununu's frontend
6
+ apps, BFFs, and shared libraries. It bundles the parsers and plugins it needs, so
7
+ consumers only install this one package.
6
8
 
7
- **Version 6.0.0+** uses ESLint v9 with the new flat config format.
9
+ > **Flat config only.** This package targets ESLint v9's flat config
10
+ > (`eslint.config.*`). There is no legacy `.eslintrc` export. (v6.0.0+ is flat
11
+ > config; v4/v5 were the legacy format.)
8
12
 
9
13
  ## 📦 Installation
10
14
 
11
- Add @kununu/eslint-config npm package as dev dependency to your project:
12
-
13
15
  ```console
14
16
  npm install --save-dev @kununu/eslint-config
15
17
  ```
16
18
 
17
- ## 💻 Usage
19
+ `typescript` is an optional peer dependency (`>=5.0.0`) — only needed for the
20
+ type-aware TypeScript rules (see below).
18
21
 
19
- ### ESLint v9 (Flat Config)
22
+ ## 💻 Usage
20
23
 
21
- Create an `eslint.config.cjs` file:
24
+ Create an **`eslint.config.mjs`** (ESM — the config is published as an ES module):
22
25
 
23
26
  ```javascript
24
27
  import kununuConfig from '@kununu/eslint-config';
25
28
 
26
29
  export default [
27
30
  ...kununuConfig,
28
- // Your custom config here
31
+ // your project-specific overrides here
29
32
  ];
30
33
  ```
31
34
 
32
- See [docs](https://eslint.org/docs/user-guide/getting-started) to find more detailed information on ESLint configuration and usage.
35
+ Add a lint script to `package.json`:
33
36
 
34
- ## ⚡️ Plugins
37
+ ```json
38
+ {
39
+ "scripts": {
40
+ "lint": "eslint ."
41
+ }
42
+ }
43
+ ```
35
44
 
36
- At kununu, [@kununu/eslint-config](https://www.npmjs.com/package/@kununu/eslint-config) and [@kununu/stylelint-config](https://www.npmjs.com/package/@kununu/stylelint-config) linters runs on every commit, but finding a lint error after push can be frustrating and waste time. In order to avoid it, editor plugins are available to warn you and validate as you code.
45
+ See the [ESLint docs](https://eslint.org/docs/latest/use/getting-started) for more
46
+ on configuration and usage.
37
47
 
38
- There's what we use and recommend:
48
+ ### TypeScript (type-aware rules)
39
49
 
40
- ### Visual Code Studio
50
+ The TS rules use `@typescript-eslint`'s `projectService`, which auto-discovers
51
+ your `tsconfig.json`. Make sure one exists at the project root, otherwise the
52
+ type-aware rules will error.
41
53
 
42
- - [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
54
+ ### Project-specific overrides
43
55
 
44
- ### Atom
56
+ Append your own flat-config objects after the spread. Scope them with `files`,
57
+ and remember **last match wins**:
58
+
59
+ ```javascript
60
+ import kununuConfig from '@kununu/eslint-config';
45
61
 
46
- - [linter-eslint](https://atom.io/packages/linter-eslint)
62
+ export default [
63
+ ...kununuConfig,
64
+ {
65
+ rules: {
66
+ 'no-console': 'off',
67
+ },
68
+ },
69
+ {
70
+ files: ['**/*.spec.*'],
71
+ rules: {
72
+ // test-only tweaks
73
+ },
74
+ },
75
+ ];
76
+ ```
77
+
78
+ ## 🎨 What's included
79
+
80
+ Built on `@eslint/js`, `typescript-eslint`, and the React ecosystem, plus kununu
81
+ conventions. Parsers are wired up automatically: **`.ts`/`.tsx`** use
82
+ `@typescript-eslint/parser` (with `projectService`), **`.js`/`.jsx`** use
83
+ `@babel/eslint-parser`.
84
+
85
+ | Area | Plugins |
86
+ | --- | --- |
87
+ | Base | `@eslint/js`, `typescript-eslint` |
88
+ | React | `eslint-plugin-react`, `eslint-plugin-react-hooks` (incl. React Compiler rules) |
89
+ | Accessibility | `eslint-plugin-jsx-a11y` |
90
+ | Style / formatting | `@stylistic/eslint-plugin` |
91
+ | Code smells | `eslint-plugin-sonarjs` |
92
+ | Imports / ordering | `eslint-plugin-perfectionist` |
93
+ | Tests (`*.spec.*`) | `eslint-plugin-jest`, `eslint-plugin-jest-dom`, `eslint-plugin-testing-library` |
94
+ | kununu-specific | `eslint-plugin-lodash`, `eslint-plugin-granular-selectors`, `@babel/eslint-plugin` |
95
+
96
+ ### Notable conventions
97
+
98
+ - **No default React import** — `import React from 'react'` is disallowed; import
99
+ named hooks/types instead (`import {useState} from 'react'`).
100
+ - **Per-method lodash imports** — `import debounce from 'lodash/debounce'`, not
101
+ `import {debounce} from 'lodash'`.
102
+ - **Import ordering** (`perfectionist/sort-imports`): `react` → types →
103
+ builtins/externals → `@kununu/*` internals → aliases → relatives.
104
+ - **Granular Redux selectors** for `use*Selector*` / `use*Store*` hooks.
105
+ - **Formatting** via `@stylistic` (120-char lines ignoring comments/strings/URLs,
106
+ semicolons, single quotes, …).
107
+ - **React Compiler rules** (`react-hooks/refs`, `set-state-in-effect`, …) are
108
+ **warnings**, not errors.
109
+ - **Test files** (`**/*.spec.*`) automatically get Jest globals plus the jest /
110
+ jest-dom / testing-library rule sets; some source-only rules (e.g.
111
+ `react/prop-types`, `sonarjs/no-hardcoded-passwords`) are relaxed there.
112
+
113
+ ## ⚡️ Editor integration
114
+
115
+ Linting runs in CI / pre-commit, but catching errors in your editor is faster. We
116
+ recommend the
117
+ [ESLint VS Code extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint).
118
+
119
+ Recent versions auto-detect flat config. If your editor still defaults to the
120
+ legacy format, enable it in `.vscode/settings.json`:
121
+
122
+ ```json
123
+ {
124
+ "eslint.useFlatConfig": true
125
+ }
126
+ ```
package/eslint.config.mjs CHANGED
@@ -25,8 +25,12 @@ export default defineConfig([
25
25
  reactPlugin.configs.flat['jsx-runtime'],
26
26
  sonarjs.configs.recommended,
27
27
  stylistic.configs.recommended,
28
- testingLibraryPlugin.configs['flat/dom'],
29
- tseslint.configs.recommended,
28
+ // Scope the TypeScript rules to TS files only; .js/.jsx use the Babel parser
29
+ // below and would otherwise run type-aware rules under the wrong parser.
30
+ ...tseslint.configs.recommended.map(config => ({
31
+ ...config,
32
+ files: ['**/*.ts', '**/*.tsx'],
33
+ })),
30
34
 
31
35
  globalIgnores([
32
36
  '**/.next/',
@@ -51,6 +55,18 @@ export default defineConfig([
51
55
  projectService: true,
52
56
  },
53
57
  },
58
+ rules: {
59
+ '@typescript-eslint/no-require-imports': 'error',
60
+ // Allow intentionally-unused identifiers prefixed with `_`.
61
+ '@typescript-eslint/no-unused-vars': ['error', {
62
+ argsIgnorePattern: '^_',
63
+ caughtErrorsIgnorePattern: '^_',
64
+ destructuredArrayIgnorePattern: '^_',
65
+ ignoreRestSiblings: true,
66
+ varsIgnorePattern: '^_',
67
+ }],
68
+ '@typescript-eslint/no-use-before-define': 'error',
69
+ },
54
70
  },
55
71
 
56
72
  {
@@ -66,18 +82,33 @@ export default defineConfig([
66
82
  },
67
83
  },
68
84
 
85
+ // Test-only configs. Spread as separate entries so their plugins/rules
86
+ // aren't clobbered, and scope them to spec files (incl. testing-library,
87
+ // which previously applied to every file).
88
+ {...pluginJest.configs['flat/recommended'], files: ['**/*.spec.*']},
89
+ {...jestDomPlugin.configs['flat/recommended'], files: ['**/*.spec.*']},
90
+ {...testingLibraryPlugin.configs['flat/dom'], files: ['**/*.spec.*']},
69
91
  {
70
- files: [
71
- ['**/*.spec.*'],
72
- ],
73
- ...jestDomPlugin.configs['flat/recommended'],
74
- languageOptions: {
75
- globals: pluginJest.environments.globals.globals,
76
- },
77
- plugins: {jest: pluginJest},
92
+ files: ['**/*.spec.*'],
78
93
  rules: {
79
94
  '@typescript-eslint/no-explicit-any': 'off',
95
+ // Tests legitimately require() dynamic mocks / json fixtures.
96
+ '@typescript-eslint/no-require-imports': 'off',
97
+ // Recognise assertions made through `assert*` helper functions, not just
98
+ // direct expect() calls.
99
+ 'jest/expect-expect': ['warn', {assertFunctionNames: ['expect', 'assert*']}],
100
+ // kununu stores shared test fixtures under __mocks__ and imports them
101
+ // directly; this rule targets jest auto-mocks, not that convention.
102
+ 'jest/no-mocks-import': 'off',
80
103
  'react/display-name': 'off',
104
+ // Prop-types are redundant in a TypeScript codebase.
105
+ 'react/prop-types': 'off',
106
+ // Test fixtures often contain password-like strings (mock query strings,
107
+ // tokens) that aren't real credentials; keep the rule for source code.
108
+ 'sonarjs/no-hardcoded-passwords': 'off',
109
+ // Direct DOM access is common and acceptable in tests.
110
+ 'testing-library/no-node-access': 'off',
111
+ 'testing-library/render-result-naming-convention': 'off',
81
112
  },
82
113
  },
83
114
 
@@ -146,7 +177,8 @@ export default defineConfig([
146
177
  {blankLine: 'any', next: 'import', prev: 'import'},
147
178
  // Always require blank line after imports when followed by non-imports
148
179
  {blankLine: 'always', next: '*', prev: 'import'},
149
- // But allow imports to be followed by imports without forcing blank line
180
+ // Re-allow consecutive imports with no blank line. Must stay AFTER the
181
+ // rule above (last match wins) or every adjacent import is forced apart.
150
182
  {blankLine: 'any', next: 'import', prev: 'import'},
151
183
  // Allow any spacing between variable declarations (before and between)
152
184
  {blankLine: 'any', next: ['const', 'let', 'var'], prev: '*'},
@@ -163,8 +195,6 @@ export default defineConfig([
163
195
  '@stylistic/quote-props': ['error', 'as-needed'],
164
196
  '@stylistic/semi': ['error', 'always'],
165
197
  '@stylistic/switch-colon-spacing': 'error',
166
- '@typescript-eslint/no-use-before-define': 'error',
167
- '@typescript-eslint/no-var-requires': 'error',
168
198
  'granular-selectors/granular-selectors': ['error', {
169
199
  include: ['use.*Selector.*', 'use.*Store.*'],
170
200
  }],
@@ -254,7 +284,14 @@ export default defineConfig([
254
284
  }],
255
285
  'prefer-template': 'error',
256
286
  'react-hooks/exhaustive-deps': 'warn',
287
+ // React Compiler rules: advisory for now. They flag patterns the compiler
288
+ // can't optimise, but the current codebases use them widely; keep as
289
+ // warnings rather than blocking errors.
290
+ 'react-hooks/immutability': 'warn',
291
+ 'react-hooks/refs': 'warn',
257
292
  'react-hooks/rules-of-hooks': 'error',
293
+ 'react-hooks/set-state-in-effect': 'warn',
294
+ 'react-hooks/use-memo': 'warn',
258
295
  'react/jsx-closing-bracket-location': ['error', 'tag-aligned'],
259
296
  // More restrictive JSX rules that are auto-fixable
260
297
  'react/jsx-curly-spacing': ['error', 'never'],
@@ -271,6 +308,8 @@ export default defineConfig([
271
308
  closingSlash: 'never',
272
309
  }],
273
310
  'sonarjs/deprecation': ['warn'],
311
+ // TypeScript already infers/checks return types; this duplicates it.
312
+ 'sonarjs/function-return-type': 'off',
274
313
  'sonarjs/todo-tag': ['warn'],
275
314
  },
276
315
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kununu/eslint-config",
3
- "version": "7.1.5",
3
+ "version": "7.3.0",
4
4
  "description": "kununu's ESLint config",
5
5
  "main": "eslint.config.mjs",
6
6
  "type": "module",
@@ -30,24 +30,24 @@
30
30
  },
31
31
  "homepage": "https://github.com/kununu/eslint-config#readme",
32
32
  "dependencies": {
33
- "@babel/core": "7.29.7",
34
- "@babel/eslint-parser": "7.29.7",
35
- "@babel/eslint-plugin": "7.29.7",
33
+ "@babel/core": "8.0.1",
34
+ "@babel/eslint-parser": "8.0.1",
35
+ "@babel/eslint-plugin": "8.0.1",
36
36
  "@eslint/js": "9.39.4",
37
37
  "@stylistic/eslint-plugin": "5.10.0",
38
- "@typescript-eslint/parser": "8.59.4",
38
+ "@typescript-eslint/parser": "8.62.0",
39
39
  "eslint": "9.39.2",
40
40
  "eslint-plugin-granular-selectors": "1.5.0",
41
- "eslint-plugin-jest": "29.15.2",
41
+ "eslint-plugin-jest": "29.15.3",
42
42
  "eslint-plugin-jest-dom": "5.5.0",
43
43
  "eslint-plugin-jsx-a11y": "6.10.2",
44
44
  "eslint-plugin-lodash": "8.0.0",
45
- "eslint-plugin-perfectionist": "5.9.0",
45
+ "eslint-plugin-perfectionist": "5.9.1",
46
46
  "eslint-plugin-react": "7.37.5",
47
47
  "eslint-plugin-react-hooks": "7.1.1",
48
- "eslint-plugin-sonarjs": "4.0.3",
48
+ "eslint-plugin-sonarjs": "4.1.0",
49
49
  "eslint-plugin-testing-library": "7.16.2",
50
- "typescript-eslint": "8.59.4"
50
+ "typescript-eslint": "8.62.0"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "typescript": ">=5.0.0"