@hayuno/eslint-config 1.0.5
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/LICENSE +21 -0
- package/README.md +96 -0
- package/index.mjs +72 -0
- package/package.json +63 -0
- package/rules/base.js +41 -0
- package/rules/custom/index.js +18 -0
- package/rules/custom/no-speculative-it.js +57 -0
- package/rules/jest.js +13 -0
- package/rules/next.js +4 -0
- package/rules/prettier.js +7 -0
- package/rules/react.js +58 -0
- package/rules/typescript.js +80 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Hayuno AG
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# @hayuno-ag/eslint-config
|
|
2
|
+
|
|
3
|
+
This packages offers configurations for ESLint and Prettier which are used for projects at Hayuno AG.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Install `eslint`, `typescript`, `@typescript-eslint/parser`, `eslint-config-prettier`, `prettier` and `@hayuno-ag/eslint-config` as dev dependencies:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install --save-dev @hayuno-ag/eslint-config eslint typescript @typescript-eslint/parser eslint-config-prettier prettier
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Note: If you're using Next.js, `next` is already expected to be installed in your project. The plugin is included as a dependency of this package: `@next/eslint-plugin-next`.
|
|
14
|
+
|
|
15
|
+
## Integration
|
|
16
|
+
|
|
17
|
+
By setting-up your `eslint.config.mjs` (example):
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import { defineConfig } from 'eslint/config';
|
|
21
|
+
import eslintConfig from '@hayuno-ag/eslint-config';
|
|
22
|
+
// additional imports
|
|
23
|
+
|
|
24
|
+
export default defineConfig([
|
|
25
|
+
globalIgnores(['**/node_modules', '**/dist', '**/build', 'bin/**', 'package-lock.json']),
|
|
26
|
+
...eslintConfig,
|
|
27
|
+
{
|
|
28
|
+
languageOptions: {
|
|
29
|
+
/* your language options */
|
|
30
|
+
},
|
|
31
|
+
rules: {
|
|
32
|
+
/* your override rules */
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
// Test-specific rules
|
|
36
|
+
{
|
|
37
|
+
files: ['tests/**/*.test.tsx', 'tests/**/*.test.ts'],
|
|
38
|
+
rules: {
|
|
39
|
+
'@hayuno-ag/no-speculative-it': 'warn',
|
|
40
|
+
/* your additional rule overrides */
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
// Ignore patterns
|
|
44
|
+
{
|
|
45
|
+
ignores: [
|
|
46
|
+
/* your ignore file patterns */
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
]);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Custom Rules Plugin
|
|
53
|
+
|
|
54
|
+
This package also offers a custom rules plugin, which can be used to add custom rules to your project.
|
|
55
|
+
|
|
56
|
+
Currently, there's only one rule: `@hayuno-ag/no-speculative-it`, defined at `rules/no-speculative-it.ts`.
|
|
57
|
+
|
|
58
|
+
### Defining additional rules
|
|
59
|
+
|
|
60
|
+
Taking `no-speculative-it.js` as template, you can easily define additional rules by just adding another
|
|
61
|
+
js-file implementing the rule and storing it at `rules/custom`. `rules/custom/index.js` will then automatically
|
|
62
|
+
load all rules from this directory and `index.mjs` will export them as long as `jest` is installed as
|
|
63
|
+
dependency in the consuming project.
|
|
64
|
+
|
|
65
|
+
By default, all newly-created rules are set to `error` severity. If you want to change this, you can
|
|
66
|
+
simply set the `meta.severity` property in the rule definition as shown in `no-speculative-it.js`.
|
|
67
|
+
|
|
68
|
+
As shown in [Integration](#integration) above, you can change a rule's severity level by adding it to the `rules`
|
|
69
|
+
property of your `eslint.config.mjs`. If you don't want to override a rule's severity level, you don't have
|
|
70
|
+
to add it to the according `rules` property. It then is executed with its default severity level.
|
|
71
|
+
|
|
72
|
+
The names of the rules defined in this project are prefixed with `@hayuno-ag/`. Therefore, `no-speculative-it`
|
|
73
|
+
is referenced by `@hayuno-ag/no-speculative-it`.
|
|
74
|
+
|
|
75
|
+
### `@hayuno-ag/no-speculative-it`
|
|
76
|
+
|
|
77
|
+
This rule is used to prevent speculative `it` statements and enforces the usage of imperative statements instead.
|
|
78
|
+
|
|
79
|
+
Example: Instead of `it('should restart the universe from the beginning')` the imperative statement
|
|
80
|
+
`it('restarts the universe from the beginning')` should be used.
|
|
81
|
+
|
|
82
|
+
Default severity: `error`.
|
|
83
|
+
|
|
84
|
+
## Additional information
|
|
85
|
+
|
|
86
|
+
This package requires the following peer dependencies to be installed in your project:
|
|
87
|
+
|
|
88
|
+
- `eslint` (>= 9.33.0)
|
|
89
|
+
- `typescript` (>= 4.0.0)
|
|
90
|
+
- `@typescript-eslint/parser` (^8.37.0)
|
|
91
|
+
- `eslint-config-prettier` (^10.1.8)
|
|
92
|
+
- `prettier` (^3.6.2)
|
|
93
|
+
- `jest` (^30.2.0) - only required if you want to use the Jest-related rules
|
|
94
|
+
|
|
95
|
+
All ESLint plugins (such as `eslint-plugin-react`, `eslint-plugin-react-hooks`, `eslint-plugin-jsx-a11y`,
|
|
96
|
+
etc.) are included as regular dependencies in this package, so you don't need to install them separately.
|
package/index.mjs
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { FlatCompat } from '@eslint/eslintrc';
|
|
5
|
+
import js from '@eslint/js';
|
|
6
|
+
import typescriptEslint from '@typescript-eslint/eslint-plugin';
|
|
7
|
+
import importPlugin from 'eslint-plugin-import';
|
|
8
|
+
import jestPlugin from 'eslint-plugin-jest';
|
|
9
|
+
import reactPlugin from 'eslint-plugin-react';
|
|
10
|
+
import reactHooksPlugin from 'eslint-plugin-react-hooks';
|
|
11
|
+
import testingLibraryPlugin from 'eslint-plugin-testing-library';
|
|
12
|
+
import jsxA11yPlugin from 'eslint-plugin-jsx-a11y';
|
|
13
|
+
import nextPlugin from '@next/eslint-plugin-next';
|
|
14
|
+
import prettierConfig from 'eslint-config-prettier';
|
|
15
|
+
|
|
16
|
+
const require = createRequire(import.meta.url);
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname = path.dirname(__filename);
|
|
19
|
+
|
|
20
|
+
const moduleExists = (module) => {
|
|
21
|
+
try {
|
|
22
|
+
require.resolve(module, {
|
|
23
|
+
paths: [process.cwd(), path.join(process.cwd(), 'node_modules')],
|
|
24
|
+
});
|
|
25
|
+
return true;
|
|
26
|
+
} catch (error) {
|
|
27
|
+
if (error && error.code === 'MODULE_NOT_FOUND') return false;
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const compat = new FlatCompat({
|
|
33
|
+
baseDirectory: __dirname,
|
|
34
|
+
recommendedConfig: js.configs.recommended,
|
|
35
|
+
allConfig: js.configs.all,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const legacyRuleConfigs = ['./rules/base'];
|
|
39
|
+
if (moduleExists('next')) legacyRuleConfigs.push('./rules/next');
|
|
40
|
+
if (moduleExists('react')) legacyRuleConfigs.push('./rules/react');
|
|
41
|
+
if (moduleExists('jest')) legacyRuleConfigs.push('./rules/jest');
|
|
42
|
+
if (moduleExists('typescript')) legacyRuleConfigs.push('./rules/typescript');
|
|
43
|
+
legacyRuleConfigs.push('./rules/prettier');
|
|
44
|
+
|
|
45
|
+
const baseConfigs = compat.extends(...legacyRuleConfigs.map(require.resolve));
|
|
46
|
+
|
|
47
|
+
const globalPlugins = [
|
|
48
|
+
{
|
|
49
|
+
plugins: {
|
|
50
|
+
'@typescript-eslint': typescriptEslint,
|
|
51
|
+
import: importPlugin,
|
|
52
|
+
jest: jestPlugin,
|
|
53
|
+
react: reactPlugin,
|
|
54
|
+
'react-hooks': reactHooksPlugin,
|
|
55
|
+
'jsx-a11y': jsxA11yPlugin,
|
|
56
|
+
'@next/next': nextPlugin,
|
|
57
|
+
'testing-library': testingLibraryPlugin,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
const customPlugin = require('./rules/custom');
|
|
63
|
+
const customRules = {
|
|
64
|
+
plugins: {
|
|
65
|
+
'@hayuno-ag': customPlugin,
|
|
66
|
+
},
|
|
67
|
+
rules: Object.fromEntries(
|
|
68
|
+
Object.entries(customPlugin.rules).map(([name, rule]) => [`@hayuno-ag/${name}`, rule.meta?.severity || 'error']),
|
|
69
|
+
),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default [...globalPlugins, ...baseConfigs, customRules, prettierConfig];
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hayuno/eslint-config",
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"description": "ESLint configuration used for projects at Hayuno AG",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"eslint",
|
|
10
|
+
"eslintconfig",
|
|
11
|
+
"typescript",
|
|
12
|
+
"prettier"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://gitlab.com/hayuno/eslint-config#hayuno-ageslint-config",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://gitlab.com/hayuno/eslint-config/issues"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+ssh://git@gitlab.com/hayuno/eslint-config.git"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": "Hayuno AG",
|
|
24
|
+
"type": "commonjs",
|
|
25
|
+
"main": "index.mjs",
|
|
26
|
+
"files": [
|
|
27
|
+
"*.js",
|
|
28
|
+
"*.mjs",
|
|
29
|
+
"rules"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"format": "prettier --check .",
|
|
33
|
+
"format:fix": "prettier --write .",
|
|
34
|
+
"prepare": "husky"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@next/eslint-plugin-next": ">=15.0.0",
|
|
38
|
+
"@typescript-eslint/eslint-plugin": "^8.37.0",
|
|
39
|
+
"eslint-plugin-import": "^2.32.0",
|
|
40
|
+
"eslint-plugin-jest": "^29.0.1",
|
|
41
|
+
"eslint-plugin-jest-dom": "^5.5.0",
|
|
42
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
43
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
44
|
+
"eslint-plugin-react": "^7.37.5",
|
|
45
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
46
|
+
"eslint-plugin-testing-library": "^7.15.1"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"husky": "^9.1.7",
|
|
50
|
+
"prettier": "^3.6.2"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"@typescript-eslint/parser": "^8.37.0",
|
|
54
|
+
"eslint": ">=9.33.0",
|
|
55
|
+
"eslint-config-prettier": "^10.1.8",
|
|
56
|
+
"jest": "^30.2.0",
|
|
57
|
+
"prettier": "^3.6.2",
|
|
58
|
+
"typescript": ">=4.0.0"
|
|
59
|
+
},
|
|
60
|
+
"engines": {
|
|
61
|
+
"node": ">=22.14.0"
|
|
62
|
+
}
|
|
63
|
+
}
|
package/rules/base.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
ignorePatterns: ['!.*'],
|
|
3
|
+
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
|
4
|
+
plugins: ['@typescript-eslint'],
|
|
5
|
+
env: {
|
|
6
|
+
browser: true,
|
|
7
|
+
node: true,
|
|
8
|
+
es2022: true,
|
|
9
|
+
},
|
|
10
|
+
parser: '@typescript-eslint/parser',
|
|
11
|
+
parserOptions: {
|
|
12
|
+
ecmaVersion: 2022,
|
|
13
|
+
sourceType: 'module',
|
|
14
|
+
},
|
|
15
|
+
reportUnusedDisableDirectives: true,
|
|
16
|
+
rules: {
|
|
17
|
+
'import/extensions': ['error', 'ignorePackages', { js: 'never', '': 'never' }],
|
|
18
|
+
'import/no-cycle': 'off',
|
|
19
|
+
'import/no-extraneous-dependencies': [
|
|
20
|
+
'error',
|
|
21
|
+
{
|
|
22
|
+
devDependencies: ['**/*.test.ts'],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
'import/no-useless-path-segments': ['error', { noUselessIndex: true }],
|
|
26
|
+
'import/order': ['error', { 'newlines-between': 'never' }],
|
|
27
|
+
'import/prefer-default-export': 'off',
|
|
28
|
+
'arrow-body-style': 'error',
|
|
29
|
+
'max-classes-per-file': 'off',
|
|
30
|
+
'max-len': ['error', { code: 120 }],
|
|
31
|
+
'no-console': 'error',
|
|
32
|
+
'no-empty-function': ['error', { allow: ['arrowFunctions'] }],
|
|
33
|
+
'no-use-before-define': ['error', { functions: false }],
|
|
34
|
+
'prefer-arrow-callback': 'error',
|
|
35
|
+
},
|
|
36
|
+
overrides: [
|
|
37
|
+
{
|
|
38
|
+
files: ['scripts/**', 'bin/**'],
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const customDir = __dirname;
|
|
5
|
+
const files = fs.readdirSync(customDir);
|
|
6
|
+
|
|
7
|
+
const ruleFiles = files.filter((file) => file.endsWith('.js') && file !== 'index.js');
|
|
8
|
+
|
|
9
|
+
const rules = {};
|
|
10
|
+
ruleFiles.forEach((file) => {
|
|
11
|
+
const filePath = path.join(customDir, file);
|
|
12
|
+
const ruleModule = require(filePath);
|
|
13
|
+
Object.assign(rules, ruleModule);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
rules,
|
|
18
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
'no-speculative-it': {
|
|
3
|
+
meta: {
|
|
4
|
+
type: 'suggestion',
|
|
5
|
+
docs: {
|
|
6
|
+
description: 'Enforce imperative mood in it-descriptions instead of "should"',
|
|
7
|
+
category: 'Best Practices',
|
|
8
|
+
recommended: false,
|
|
9
|
+
},
|
|
10
|
+
fixable: null,
|
|
11
|
+
schema: [],
|
|
12
|
+
messages: {
|
|
13
|
+
noShould: 'Prefer using imperative mood (e.g. "{{suggestion}}") instead of "should {{action}}"',
|
|
14
|
+
},
|
|
15
|
+
severity: 'error',
|
|
16
|
+
},
|
|
17
|
+
create(context) {
|
|
18
|
+
const shouldPattern = /^should\s+(.+)/i;
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
CallExpression(node) {
|
|
22
|
+
if (node.callee.type === 'Identifier' && node.callee.name === 'it' && node.arguments.length > 0) {
|
|
23
|
+
const firstArg = node.arguments[0];
|
|
24
|
+
|
|
25
|
+
if (firstArg.type === 'Literal' && typeof firstArg.value === 'string') {
|
|
26
|
+
const match = firstArg.value.match(shouldPattern);
|
|
27
|
+
|
|
28
|
+
if (match) {
|
|
29
|
+
const action = match[1];
|
|
30
|
+
const suggestion = action.replace(/^(\w+)/, (word) => {
|
|
31
|
+
switch (word) {
|
|
32
|
+
case 'not':
|
|
33
|
+
return 'does not';
|
|
34
|
+
case 'be':
|
|
35
|
+
return 'is/has';
|
|
36
|
+
}
|
|
37
|
+
if (word.endsWith('y')) return word.slice(0, -1) + 'ies';
|
|
38
|
+
if (word.endsWith('ch')) return word + 'es';
|
|
39
|
+
return word + 's';
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
context.report({
|
|
43
|
+
node: firstArg,
|
|
44
|
+
messageId: 'noShould',
|
|
45
|
+
data: {
|
|
46
|
+
action,
|
|
47
|
+
suggestion,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
package/rules/jest.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
overrides: [
|
|
3
|
+
{
|
|
4
|
+
files: ['*.test.*'],
|
|
5
|
+
extends: ['plugin:jest/recommended', 'plugin:jest-dom/recommended'],
|
|
6
|
+
env: { 'jest/globals': true },
|
|
7
|
+
rules: {
|
|
8
|
+
'require-await': 'error',
|
|
9
|
+
'jest/consistent-test-it': ['error', { fn: 'it', withinDescribe: 'it' }],
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
};
|
package/rules/next.js
ADDED
package/rules/react.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended', 'plugin:jsx-a11y/recommended'],
|
|
3
|
+
rules: {
|
|
4
|
+
'react/default-props-match-prop-types': 'off',
|
|
5
|
+
'react/destructuring-assignment': ['error', 'always', { ignoreClassFields: true }],
|
|
6
|
+
'react/function-component-definition': [
|
|
7
|
+
'error',
|
|
8
|
+
{
|
|
9
|
+
unnamedComponents: 'arrow-function',
|
|
10
|
+
namedComponents: ['arrow-function', 'function-declaration'],
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
'react/jsx-filename-extension': ['error', { extensions: ['.js', '.jsx'] }],
|
|
14
|
+
'react/jsx-props-no-spreading': 'off',
|
|
15
|
+
'react/no-unused-prop-types': 'off',
|
|
16
|
+
'react/prop-types': 'off',
|
|
17
|
+
'react/react-in-jsx-scope': 'off',
|
|
18
|
+
'react/require-default-props': 'off',
|
|
19
|
+
'react/state-in-constructor': 'off',
|
|
20
|
+
'import/order': [
|
|
21
|
+
'error',
|
|
22
|
+
{
|
|
23
|
+
pathGroups: [{ pattern: 'react', group: 'external', position: 'before' }],
|
|
24
|
+
pathGroupsExcludedImportTypes: ['react'],
|
|
25
|
+
'newlines-between': 'never',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
'jsx-a11y/anchor-is-valid': [
|
|
29
|
+
'error',
|
|
30
|
+
{
|
|
31
|
+
specialLink: ['hrefLeft', 'hrefRight', 'to'],
|
|
32
|
+
aspects: ['noHref', 'invalidHref', 'preferButton'],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
'no-restricted-globals': ['error', { name: 'React', message: 'Prefer importing from "react".' }],
|
|
36
|
+
'no-restricted-imports': [
|
|
37
|
+
'error',
|
|
38
|
+
{
|
|
39
|
+
name: 'react',
|
|
40
|
+
importNames: ['default'],
|
|
41
|
+
message: 'Prefer using named exports.',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'react',
|
|
45
|
+
importNames: ['FC'],
|
|
46
|
+
message: 'Prefer type inference for component return types.',
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
overrides: [
|
|
51
|
+
{
|
|
52
|
+
files: ['*.ts', '*.tsx'],
|
|
53
|
+
rules: {
|
|
54
|
+
'react/jsx-filename-extension': ['error', { extensions: ['.tsx'] }],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
settings: {
|
|
3
|
+
react: {
|
|
4
|
+
version: 'detect',
|
|
5
|
+
},
|
|
6
|
+
'import/extensions': ['.ts', '.tsx'],
|
|
7
|
+
'import/parsers': {
|
|
8
|
+
'@typescript-eslint/parser': ['.ts', '.tsx'],
|
|
9
|
+
},
|
|
10
|
+
'import/resolver': {
|
|
11
|
+
node: {
|
|
12
|
+
extensions: ['.ts', '.tsx'],
|
|
13
|
+
moduleDirectory: ['node_modules', 'src/'],
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
rules: {
|
|
18
|
+
'import/extensions': [
|
|
19
|
+
'error',
|
|
20
|
+
'ignorePackages',
|
|
21
|
+
{
|
|
22
|
+
js: 'never',
|
|
23
|
+
ts: 'never',
|
|
24
|
+
tsx: 'never',
|
|
25
|
+
'': 'never',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
overrides: [
|
|
30
|
+
{
|
|
31
|
+
files: ['*.ts', '*.tsx'],
|
|
32
|
+
parser: '@typescript-eslint/parser',
|
|
33
|
+
plugins: ['@typescript-eslint'],
|
|
34
|
+
extends: [
|
|
35
|
+
'plugin:@typescript-eslint/recommended',
|
|
36
|
+
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
|
37
|
+
],
|
|
38
|
+
parserOptions: {
|
|
39
|
+
project: ['./tsconfig.json', './**/tsconfig.json'],
|
|
40
|
+
createDefaultProgram: true,
|
|
41
|
+
ecmaVersion: 2022,
|
|
42
|
+
sourceType: 'module',
|
|
43
|
+
},
|
|
44
|
+
rules: {
|
|
45
|
+
'@typescript-eslint/consistent-type-imports': 'error',
|
|
46
|
+
'@typescript-eslint/default-param-last': 'error',
|
|
47
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
48
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
49
|
+
'@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }],
|
|
50
|
+
'@typescript-eslint/no-explicit-any': 'error',
|
|
51
|
+
'@typescript-eslint/no-unused-vars': [
|
|
52
|
+
'error',
|
|
53
|
+
{
|
|
54
|
+
args: 'all',
|
|
55
|
+
argsIgnorePattern: '^_',
|
|
56
|
+
caughtErrors: 'all',
|
|
57
|
+
caughtErrorsIgnorePattern: '^_',
|
|
58
|
+
destructuredArrayIgnorePattern: '^_',
|
|
59
|
+
varsIgnorePattern: '^_',
|
|
60
|
+
ignoreRestSiblings: true,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
'@typescript-eslint/no-use-before-define': ['error', { functions: false }],
|
|
64
|
+
'@typescript-eslint/no-useless-constructor': 'error',
|
|
65
|
+
'@typescript-eslint/switch-exhaustiveness-check': 'error',
|
|
66
|
+
'import/no-unresolved': 'off',
|
|
67
|
+
'consistent-return': 'off',
|
|
68
|
+
'default-case': 'off',
|
|
69
|
+
'default-param-last': 'off',
|
|
70
|
+
'no-empty-function': 'off',
|
|
71
|
+
'no-restricted-syntax': [
|
|
72
|
+
'error',
|
|
73
|
+
{ selector: 'TSEnumDeclaration', message: 'Prefer types over enums because enums are not type-safe.' },
|
|
74
|
+
],
|
|
75
|
+
'no-use-before-define': 'off',
|
|
76
|
+
'no-useless-constructor': 'off',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
};
|