apic-eslint-config 1.0.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.
Files changed (3) hide show
  1. package/base.js +216 -0
  2. package/package.json +26 -0
  3. package/react.js +126 -0
package/base.js ADDED
@@ -0,0 +1,216 @@
1
+ import js from '@eslint/js';
2
+ import stylistic from '@stylistic/eslint-plugin';
3
+ import { defineConfig } from 'eslint/config';
4
+ import importPlugin from 'eslint-plugin-import';
5
+ import perfectionist from 'eslint-plugin-perfectionist';
6
+ import simpleImportSort from 'eslint-plugin-simple-import-sort';
7
+ // import eslintConfigPrettier from 'eslint-config-prettier';
8
+ import sonarjs from 'eslint-plugin-sonarjs';
9
+ import unicorn from 'eslint-plugin-unicorn';
10
+ import tseslint from 'typescript-eslint';
11
+
12
+ /**
13
+ * A shared ESLint configuration for the repository.
14
+ *
15
+ * @type {import('eslint').Linter.Config[]}
16
+ * */
17
+ export const config = defineConfig(
18
+ js.configs.recommended,
19
+ tseslint.configs.recommended,
20
+ // eslintConfigPrettier,
21
+ sonarjs.configs.recommended,
22
+ unicorn.configs.recommended,
23
+ importPlugin.flatConfigs.recommended,
24
+ importPlugin.flatConfigs.typescript,
25
+ {
26
+ languageOptions: {
27
+ parserOptions: {
28
+ projectService: {
29
+ allowDefaultProject: ['*.ts'],
30
+ },
31
+ },
32
+ },
33
+ ignores: ['dist/**', 'node_modules/**', 'coverage/**', '**/*.d.ts'],
34
+ plugins: {
35
+ '@stylistic': stylistic,
36
+ 'simple-import-sort': simpleImportSort,
37
+ perfectionist,
38
+ },
39
+ rules: {
40
+ // ESLint Possible Problems
41
+ 'array-callback-return': 'error',
42
+ 'no-constant-binary-expression': 'error',
43
+ 'no-promise-executor-return': 'error',
44
+ 'no-self-compare': 'error',
45
+ 'no-template-curly-in-string': 'error',
46
+ 'no-unreachable-loop': 'error',
47
+ 'no-unused-vars': 'off',
48
+
49
+ // ESLint Suggestions
50
+ 'arrow-body-style': ['error', 'as-needed'],
51
+ 'block-scoped-var': 'error',
52
+ camelcase: [
53
+ 'error',
54
+ {
55
+ ignoreDestructuring: true,
56
+ ignoreImports: true,
57
+ ignoreGlobals: true,
58
+ },
59
+ ],
60
+ 'no-param-reassign': [
61
+ 'error',
62
+ {
63
+ props: true,
64
+ },
65
+ ],
66
+ 'no-restricted-syntax': ['error', 'ForInStatement', 'LabeledStatement', 'WithStatement'],
67
+ 'no-implicit-coercion': 'error',
68
+ 'no-console': ['error', { allow: ['error'] }],
69
+ 'default-case': 'error',
70
+ 'default-case-last': 'error',
71
+ 'dot-notation': 'off',
72
+ eqeqeq: [
73
+ 'error',
74
+ 'always',
75
+ {
76
+ null: 'ignore',
77
+ },
78
+ ],
79
+ 'func-style': [
80
+ 'error',
81
+ 'declaration',
82
+ {
83
+ allowArrowFunctions: true,
84
+ },
85
+ ],
86
+ 'no-else-return': [
87
+ 'error',
88
+ {
89
+ allowElseIf: false,
90
+ },
91
+ ],
92
+ 'no-alert': 'error',
93
+ 'no-eval': 'error',
94
+ 'no-implied-eval': 'error',
95
+ 'no-shadow': 'off',
96
+ 'no-empty-function': 'off',
97
+ 'no-restricted-imports': 'off',
98
+ 'no-lonely-if': 'error',
99
+ 'no-loop-func': 'error',
100
+ 'no-negated-condition': 'error',
101
+ 'no-plusplus': 'error',
102
+ 'object-shorthand': ['error', 'properties'],
103
+ 'perfectionist/sort-object-types': ['error', { partitionByNewLine: true, partitionByComment: true }],
104
+ 'perfectionist/sort-objects': ['error', { partitionByNewLine: true, partitionByComment: true }],
105
+ 'perfectionist/sort-sets': 'error',
106
+ 'perfectionist/sort-switch-case': 'error',
107
+ 'perfectionist/sort-union-types': 'error',
108
+ 'sort-keys': 'off',
109
+
110
+ // Stylistic
111
+ '@stylistic/padding-line-between-statements': [
112
+ 'error',
113
+ {
114
+ blankLine: 'always',
115
+ prev: '*',
116
+ next: [
117
+ 'return',
118
+ 'block',
119
+ 'multiline-block-like',
120
+ 'multiline-expression',
121
+ 'interface',
122
+ 'type',
123
+ 'function-overload',
124
+ ],
125
+ },
126
+ ],
127
+
128
+ // Typescript
129
+ '@typescript-eslint/consistent-generic-constructors': 'error',
130
+ '@typescript-eslint/consistent-type-definitions': ['error', 'type'],
131
+ '@typescript-eslint/consistent-type-imports': [
132
+ 'error',
133
+ {
134
+ prefer: 'no-type-imports',
135
+ },
136
+ ],
137
+ '@typescript-eslint/dot-notation': 'error',
138
+ '@typescript-eslint/no-array-delete': 'error',
139
+ '@typescript-eslint/no-unused-vars': [
140
+ 'error',
141
+ {
142
+ argsIgnorePattern: '^_',
143
+ varsIgnorePattern: '^_',
144
+ },
145
+ ],
146
+ '@typescript-eslint/no-empty-function': 'error',
147
+ '@typescript-eslint/no-restricted-imports': 'error',
148
+ '@typescript-eslint/no-shadow': 'error',
149
+ '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error',
150
+ '@typescript-eslint/no-unnecessary-condition': 'error',
151
+ '@typescript-eslint/no-unnecessary-type-arguments': 'error',
152
+ '@typescript-eslint/prefer-reduce-type-parameter': 'error',
153
+ '@typescript-eslint/require-array-sort-compare': 'error',
154
+ '@typescript-eslint/naming-convention': [
155
+ 'error',
156
+ {
157
+ selector: 'typeLike',
158
+ format: ['StrictPascalCase'],
159
+ },
160
+ {
161
+ selector: 'interface',
162
+ format: ['StrictPascalCase'],
163
+ custom: {
164
+ regex: '^I[A-Z]',
165
+ match: false,
166
+ },
167
+ },
168
+ {
169
+ selector: 'typeParameter',
170
+ format: ['PascalCase'],
171
+ },
172
+ ],
173
+
174
+ // Import
175
+ 'import/no-unresolved': 'error',
176
+ 'import/order': 'off',
177
+ 'import/no-named-as-default-member': 'off',
178
+ 'import/namespace': 'off',
179
+ 'import/no-cycle': 'error',
180
+
181
+ // Simple import
182
+ 'simple-import-sort/exports': 'error',
183
+
184
+ // Unicorn
185
+ 'unicorn/no-null': 'off',
186
+ 'unicorn/prefer-ternary': 'off',
187
+ 'unicorn/filename-case': [
188
+ 'error',
189
+ {
190
+ cases: {
191
+ pascalCase: true,
192
+ camelCase: true,
193
+ },
194
+ },
195
+ ],
196
+ 'unicorn/prevent-abbreviations': [
197
+ 'error',
198
+ {
199
+ replacements: {
200
+ arg: false,
201
+ args: false,
202
+ env: false,
203
+ envs: false,
204
+ fn: false,
205
+ param: false,
206
+ params: false,
207
+ prop: false,
208
+ props: false,
209
+ ref: false,
210
+ refs: false,
211
+ },
212
+ },
213
+ ],
214
+ },
215
+ },
216
+ );
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "apic-eslint-config",
3
+ "version": "1.0.0",
4
+ "files": [
5
+ "base.js",
6
+ "react.js"
7
+ ],
8
+ "devDependencies": {
9
+ "@eslint/js": "^9.39.2",
10
+ "@stylistic/eslint-plugin": "^5.6.1",
11
+ "@types/eslint-plugin-jsx-a11y": "^6.10.1",
12
+ "eslint-config-prettier": "^10.1.8",
13
+ "eslint-plugin-import": "^2.32.0",
14
+ "eslint-plugin-jsx-a11y": "^6.10.2",
15
+ "eslint-plugin-perfectionist": "^5.1.0",
16
+ "eslint-plugin-react": "^7.37.5",
17
+ "eslint-plugin-react-hooks": "^7.0.1",
18
+ "eslint-plugin-simple-import-sort": "^12.1.1",
19
+ "eslint-plugin-sonarjs": "^3.0.5",
20
+ "eslint-plugin-unicorn": "^62.0.0",
21
+ "typescript-eslint": "^8.50.1"
22
+ },
23
+ "peerDependencies": {
24
+ "eslint": ">= 9"
25
+ }
26
+ }
package/react.js ADDED
@@ -0,0 +1,126 @@
1
+ import { defineConfig } from 'eslint/config';
2
+ import pluginJsxA11y from 'eslint-plugin-jsx-a11y';
3
+ import pluginReact from 'eslint-plugin-react';
4
+ import pluginReactHooks from 'eslint-plugin-react-hooks';
5
+
6
+ import * as base from './base';
7
+
8
+ /**
9
+ * A custom ESLint configuration for libraries that use React.
10
+ *
11
+ * @type {import('eslint').Linter.Config[]} */
12
+ export const config = defineConfig(
13
+ base.config,
14
+ pluginReact.configs.flat.recommended,
15
+ pluginReact.configs.flat['jsx-runtime'],
16
+ pluginReactHooks.configs.flat.recommended,
17
+ pluginJsxA11y.flatConfigs.recommended,
18
+ {
19
+ rules: {
20
+ // React
21
+ // 'react/boolean-prop-naming': ['error', {
22
+ // rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+',
23
+ // message: 'Property \'{{ propName }}\' should start with 'is' or 'has'.'
24
+ // }],
25
+ 'react/button-has-type': 'error',
26
+ 'react/display-name': ['off', { ignoreTranspilerName: false }],
27
+ 'react/forbid-component-props': ['off', { forbid: [] }],
28
+ 'react/forbid-elements': ['off', { forbid: [] }],
29
+ 'react/function-component-definition': [
30
+ 'error',
31
+ {
32
+ namedComponents: 'function-declaration',
33
+ unnamedComponents: 'arrow-function',
34
+ },
35
+ ],
36
+ 'react/hook-use-state': [
37
+ 'error',
38
+ {
39
+ allowDestructuredState: true,
40
+ },
41
+ ],
42
+ 'react/jsx-boolean-value': ['error', 'never', { always: [] }],
43
+ 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }],
44
+ 'react/jsx-fragments': ['error', 'syntax'],
45
+ // 'react/jsx-handler-names': [
46
+ // 'error',
47
+ // {
48
+ // eventHandlerPrefix: 'handle',
49
+ // eventHandlerPropPrefix: 'on',
50
+ // checkLocalVariables: true,
51
+ // },
52
+ // ],
53
+ 'react/jsx-key': [
54
+ 'error',
55
+ {
56
+ warnOnDuplicates: true,
57
+ },
58
+ ],
59
+ 'react/jsx-newline': [
60
+ 'error',
61
+ {
62
+ prevent: true,
63
+ allowMultilines: true,
64
+ },
65
+ ],
66
+ 'react/jsx-no-constructed-context-values': 'error',
67
+ 'react/jsx-no-leaked-render': [
68
+ 'error',
69
+ {
70
+ validStrategies: ['coerce', 'ternary'],
71
+ },
72
+ ],
73
+ 'react/jsx-no-script-url': [
74
+ 'error',
75
+ [
76
+ {
77
+ name: 'Link',
78
+ props: ['to'],
79
+ },
80
+ ],
81
+ ],
82
+ 'react/jsx-no-useless-fragment': 'error',
83
+ 'react/jsx-pascal-case': [
84
+ 'error',
85
+ {
86
+ allowAllCaps: true,
87
+ ignore: [],
88
+ },
89
+ ],
90
+
91
+ 'react/no-array-index-key': 'error',
92
+ 'react/no-namespace': 'error',
93
+ 'react/no-object-type-as-default-prop': 'error',
94
+ 'react/no-this-in-sfc': 'error',
95
+ 'react/no-unstable-nested-components': 'error',
96
+ 'react/no-unused-prop-types': 'error',
97
+ 'react/self-closing-comp': 'error',
98
+ 'react/void-dom-elements-no-children': 'error',
99
+
100
+ // React Hooks
101
+ 'react-hooks/rules-of-hooks': 'error',
102
+ 'react-hooks/exhaustive-deps': 'error',
103
+
104
+ //#region Props sorting
105
+ // Using react/jsx-sort-props for now is enough.
106
+ // It provides conventional sorting of JSX props.
107
+ //
108
+ // If we later need more advanced ordering (grouping, placing styles/className first, etc.),
109
+ // we can switch to perfectionist/sort-jsx-props.
110
+ //
111
+ // ⚠️ Never enable perfectionist/sort-jsx-props without first configuring its groups and options;
112
+ // by default it only sorts props alphabetically.
113
+ 'react/jsx-sort-props': [
114
+ 'error',
115
+ {
116
+ reservedFirst: true,
117
+ ignoreCase: true,
118
+ callbacksLast: true,
119
+ shorthandFirst: true,
120
+ multiline: 'last',
121
+ },
122
+ ],
123
+ // 'perfectionist/sort-jsx-props': 'error',
124
+ },
125
+ },
126
+ );