@websolutespa/eslint-config 3.1.2 → 4.0.0-next.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @websolutespa/eslint-config
2
2
 
3
+ ## 4.0.0-next.6
4
+
5
+ ### Minor Changes
6
+
7
+ - aa3870b: Adds oxlint presets, `@websolutespa/eslint-config/oxlint` (`base`, `react`, `next`, `plugin`), generated from the ESLint presets with every rule as a warning. Use them from an `oxlint.config.ts`:
8
+
9
+ ```ts
10
+ import { next } from "@websolutespa/eslint-config/oxlint";
11
+ import { defineConfig } from "oxlint";
12
+ export default defineConfig(next);
13
+ ```
14
+
15
+ Run `oxlint --type-aware` (with `oxlint-tsgolint`) for the promise rules. The ESLint flat configs are still exported for one more release.
16
+
17
+ ## 3.0.1-next.0
18
+
19
+ ### Patch Changes
20
+
21
+ - Add a `no-restricted-imports` rule for `next/headers` outside `src/app` and route handlers.
22
+
3
23
  ## 3.1.2
4
24
 
5
25
  ## 3.1.1
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # @websolutespa/eslint-config
2
-
3
- [![npm version](https://badge.fury.io/js/@websolutespa/eslint-config.svg)](https://badge.fury.io/js/@websolutespa/eslint-config)
4
-
5
- Eslint shared config of the [BOM Repository](https://github.com/websolutespa/bom) by [websolute](https://www.websolute.com/).
6
-
7
- This package provides Websolute's .eslintrc as an extensible shared config.
8
-
9
- ---
10
-
11
- ##### *this library is for internal usage and not production ready*
1
+ # @websolutespa/eslint-config
2
+
3
+ [![npm version](https://badge.fury.io/js/@websolutespa/eslint-config.svg)](https://badge.fury.io/js/@websolutespa/eslint-config)
4
+
5
+ Eslint shared config of the [BOM Repository](https://github.com/websolutespa/bom) by [websolute](https://www.websolute.com/).
6
+
7
+ This package provides Websolute's .eslintrc as an extensible shared config.
8
+
9
+ ---
10
+
11
+ ##### _this library is for internal usage and not production ready_
package/base.js CHANGED
@@ -1,115 +1,126 @@
1
- import js from '@eslint/js';
2
- import stylistic from '@stylistic/eslint-plugin';
3
- import prettier from 'eslint-config-prettier';
4
- import onlyWarn from 'eslint-plugin-only-warn';
5
- import turbo from 'eslint-plugin-turbo';
6
- import typescript from 'typescript-eslint';
7
-
8
- /**
9
- * A shared ESLint configuration for the repository.
10
- *
11
- * @type {import("eslint").Linter.Config[]}
12
- * */
13
- export const base = [
14
- js.configs.recommended,
15
- prettier,
16
- ...typescript.configs.recommended,
17
- /*
18
- {
19
- rules: [
20
- ...typescript.configs.recommended.rules,
21
- ...typescript.configs['recommended-requiring-type-checking'].rules,
22
- ]
23
- },
24
- */
25
- {
26
- plugins: {
27
- turbo,
28
- },
29
- rules: {
30
- 'turbo/no-undeclared-env-vars': 'warn',
31
- },
32
- },
33
- {
34
- plugins: {
35
- onlyWarn,
36
- },
37
- },
38
- {
39
- // Helpers must not read request data: only the template (page, layout,
40
- // route handler) reads headers()/cookies()/draftMode() and passes it down.
41
- rules: {
42
- 'no-restricted-imports': ['warn', {
43
- paths: [{
44
- name: 'next/headers',
45
- message: 'Read request data (headers, cookies, draftMode) in the template under src/app and pass it down as an argument.',
46
- }],
47
- }],
48
- },
49
- },
50
- {
51
- files: [
52
- 'src/app/**',
53
- '**/handlers/**',
54
- '**/*.test.{ts,tsx}',
55
- ],
56
- rules: {
57
- 'no-restricted-imports': 'off',
58
- },
59
- },
60
- {
61
- ignores: [
62
- '**/.next/**',
63
- '**/.rollup.cache/**',
64
- '**/.turbo/**',
65
- '**/build/**',
66
- '**/dist/**',
67
- 'src/app/(payload)/**',
68
- ],
69
- },
70
- {
71
- plugins: { '@stylistic': stylistic },
72
- rules: {
73
- '@stylistic/quotes': ['error', 'single'],
74
- '@stylistic/comma-dangle': ['warn', {
75
- 'arrays': 'always-multiline',
76
- 'objects': 'always-multiline',
77
- 'imports': 'never',
78
- 'exports': 'never',
79
- 'functions': 'never',
80
- }],
81
- 'for-direction': 'off',
82
- '@stylistic/indent': ['error', 2, {
83
- 'SwitchCase': 1,
84
- }],
85
- '@stylistic/jsx-quotes': ['error', 'prefer-double'],
86
- 'no-cond-assign': ['error', 'always'],
87
- 'no-empty-function': 'off',
88
- 'no-empty': 'warn',
89
- '@stylistic/no-extra-semi': 'error',
90
- '@stylistic/no-multi-spaces': 'error',
91
- 'no-unreachable': 'error',
92
- 'no-unused-vars': 'off',
93
- '@stylistic/semi': 'error',
94
- },
95
- }, {
96
- files: [
97
- '*.{ts,tsx}',
98
- ],
99
- rules: {
100
- '@typescript-eslint/ban-types': 'off',
101
- '@typescript-eslint/explicit-module-boundary-types': 'off',
102
- '@typescript-eslint/no-empty-function': 'off',
103
- '@typescript-eslint/no-empty-interface': 'off',
104
- '@typescript-eslint/no-explicit-any': 'warn',
105
- '@typescript-eslint/no-inferrable-types': 'off',
106
- '@typescript-eslint/no-unused-vars': 'warn',
107
- '@typescript-eslint/no-use-before-define': ['error', {
108
- 'functions': false,
109
- 'classes': false,
110
- 'variables': true,
111
- 'allowNamedExports': false,
112
- }],
113
- },
114
- },
115
- ];
1
+ import js from '@eslint/js';
2
+ import stylistic from '@stylistic/eslint-plugin';
3
+ import prettier from 'eslint-config-prettier';
4
+ import onlyWarn from 'eslint-plugin-only-warn';
5
+ import turbo from 'eslint-plugin-turbo';
6
+ import typescript from 'typescript-eslint';
7
+
8
+ /**
9
+ * A shared ESLint configuration for the repository.
10
+ *
11
+ * @type {import("eslint").Linter.Config[]}
12
+ * */
13
+ export const base = [
14
+ js.configs.recommended,
15
+ prettier,
16
+ ...typescript.configs.recommended,
17
+ /*
18
+ {
19
+ rules: [
20
+ ...typescript.configs.recommended.rules,
21
+ ...typescript.configs['recommended-requiring-type-checking'].rules,
22
+ ]
23
+ },
24
+ */
25
+ {
26
+ plugins: {
27
+ turbo,
28
+ },
29
+ rules: {
30
+ 'turbo/no-undeclared-env-vars': 'warn',
31
+ },
32
+ },
33
+ {
34
+ plugins: {
35
+ onlyWarn,
36
+ },
37
+ },
38
+ {
39
+ // Helpers must not read request data: only the template (page, layout,
40
+ // route handler) reads headers()/cookies()/draftMode() and passes it down.
41
+ rules: {
42
+ 'no-restricted-imports': [
43
+ 'warn',
44
+ {
45
+ paths: [
46
+ {
47
+ name: 'next/headers',
48
+ message:
49
+ 'Read request data (headers, cookies, draftMode) in the template under src/app and pass it down as an argument.',
50
+ },
51
+ ],
52
+ },
53
+ ],
54
+ },
55
+ },
56
+ {
57
+ files: ['src/app/**', '**/handlers/**', '**/*.test.{ts,tsx}'],
58
+ rules: {
59
+ 'no-restricted-imports': 'off',
60
+ },
61
+ },
62
+ {
63
+ ignores: [
64
+ '**/.next/**',
65
+ '**/.rollup.cache/**',
66
+ '**/.turbo/**',
67
+ '**/build/**',
68
+ '**/dist/**',
69
+ 'src/app/(payload)/**',
70
+ ],
71
+ },
72
+ {
73
+ plugins: { '@stylistic': stylistic },
74
+ rules: {
75
+ '@stylistic/quotes': ['error', 'single'],
76
+ '@stylistic/comma-dangle': [
77
+ 'warn',
78
+ {
79
+ arrays: 'always-multiline',
80
+ objects: 'always-multiline',
81
+ imports: 'never',
82
+ exports: 'never',
83
+ functions: 'never',
84
+ },
85
+ ],
86
+ 'for-direction': 'off',
87
+ '@stylistic/indent': [
88
+ 'error',
89
+ 2,
90
+ {
91
+ SwitchCase: 1,
92
+ },
93
+ ],
94
+ '@stylistic/jsx-quotes': ['error', 'prefer-double'],
95
+ 'no-cond-assign': ['error', 'always'],
96
+ 'no-empty-function': 'off',
97
+ 'no-empty': 'warn',
98
+ '@stylistic/no-extra-semi': 'error',
99
+ '@stylistic/no-multi-spaces': 'error',
100
+ 'no-unreachable': 'error',
101
+ 'no-unused-vars': 'off',
102
+ '@stylistic/semi': 'error',
103
+ },
104
+ },
105
+ {
106
+ files: ['*.{ts,tsx}'],
107
+ rules: {
108
+ '@typescript-eslint/ban-types': 'off',
109
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
110
+ '@typescript-eslint/no-empty-function': 'off',
111
+ '@typescript-eslint/no-empty-interface': 'off',
112
+ '@typescript-eslint/no-explicit-any': 'warn',
113
+ '@typescript-eslint/no-inferrable-types': 'off',
114
+ '@typescript-eslint/no-unused-vars': 'warn',
115
+ '@typescript-eslint/no-use-before-define': [
116
+ 'error',
117
+ {
118
+ functions: false,
119
+ classes: false,
120
+ variables: true,
121
+ allowNamedExports: false,
122
+ },
123
+ ],
124
+ },
125
+ },
126
+ ];
package/next.js CHANGED
@@ -1,79 +1,77 @@
1
- import nextPlugin from '@next/eslint-plugin-next';
2
- import { fixupPluginRules } from '@eslint/compat';
3
- import reactPluginSource from 'eslint-plugin-react';
4
- import reactHooks from 'eslint-plugin-react-hooks';
5
- import globals from 'globals';
6
- import { base } from './base.js';
7
-
8
- // eslint-plugin-react uses context methods removed in eslint 10
9
- const reactPlugin = fixupPluginRules(reactPluginSource);
10
- const reactRecommended = {
11
- ...reactPluginSource.configs.flat.recommended,
12
- plugins: { react: reactPlugin },
13
- };
14
-
15
- /**
16
- * A custom ESLint configuration for libraries that use Next.js.
17
- *
18
- * @type {import("eslint").Linter.Config[]}
19
- * */
20
- export const next = [
21
- ...base,
22
- {
23
- ...reactRecommended,
24
- languageOptions: {
25
- ...reactRecommended.languageOptions,
26
- globals: {
27
- ...globals.serviceworker,
28
- },
29
- },
30
- },
31
- {
32
- plugins: {
33
- '@next/next': nextPlugin,
34
- },
35
- rules: {
36
- ...nextPlugin.configs.recommended.rules,
37
- ...nextPlugin.configs['core-web-vitals'].rules,
38
- },
39
- },
40
- {
41
- plugins: {
42
- 'react-hooks': reactHooks,
43
- },
44
- settings: { react: { version: 'detect' } },
45
- rules: {
46
- ...reactHooks.configs.recommended.rules,
47
- // React scope no longer necessary with new JSX transform.
48
- 'react/react-in-jsx-scope': 'off',
49
- },
50
- },
51
- {
52
- files: [
53
- '*.{ts,tsx}',
54
- ],
55
- rules: {
56
- '@typescript-eslint/ban-ts-comment': 'warn',
57
- '@typescript-eslint/no-empty-object-type': 'warn',
58
- '@typescript-eslint/no-explicit-any': 'warn',
59
- '@typescript-eslint/no-unused-vars': 'warn',
60
- /*
61
- '@typescript-eslint/no-unused-vars': [
62
- 'warn',
63
- {
64
- vars: 'all',
65
- args: 'after-used',
66
- ignoreRestSiblings: false,
67
- argsIgnorePattern: '^_',
68
- varsIgnorePattern: '^_',
69
- destructuredArrayIgnorePattern: '^_',
70
- caughtErrorsIgnorePattern: '^(_|ignore)',
71
- },
72
- ],
73
- */
74
- },
75
- },
76
- {
77
- ignores: ['.next/'],
78
- },
79
- ];
1
+ import nextPlugin from '@next/eslint-plugin-next';
2
+ import { fixupPluginRules } from '@eslint/compat';
3
+ import reactPluginSource from 'eslint-plugin-react';
4
+ import reactHooks from 'eslint-plugin-react-hooks';
5
+ import globals from 'globals';
6
+ import { base } from './base.js';
7
+
8
+ // eslint-plugin-react uses context methods removed in eslint 10
9
+ const reactPlugin = fixupPluginRules(reactPluginSource);
10
+ const reactRecommended = {
11
+ ...reactPluginSource.configs.flat.recommended,
12
+ plugins: { react: reactPlugin },
13
+ };
14
+
15
+ /**
16
+ * A custom ESLint configuration for libraries that use Next.js.
17
+ *
18
+ * @type {import("eslint").Linter.Config[]}
19
+ * */
20
+ export const next = [
21
+ ...base,
22
+ {
23
+ ...reactRecommended,
24
+ languageOptions: {
25
+ ...reactRecommended.languageOptions,
26
+ globals: {
27
+ ...globals.serviceworker,
28
+ },
29
+ },
30
+ },
31
+ {
32
+ plugins: {
33
+ '@next/next': nextPlugin,
34
+ },
35
+ rules: {
36
+ ...nextPlugin.configs.recommended.rules,
37
+ ...nextPlugin.configs['core-web-vitals'].rules,
38
+ },
39
+ },
40
+ {
41
+ plugins: {
42
+ 'react-hooks': reactHooks,
43
+ },
44
+ settings: { react: { version: 'detect' } },
45
+ rules: {
46
+ ...reactHooks.configs.recommended.rules,
47
+ // React scope no longer necessary with new JSX transform.
48
+ 'react/react-in-jsx-scope': 'off',
49
+ },
50
+ },
51
+ {
52
+ files: ['*.{ts,tsx}'],
53
+ rules: {
54
+ '@typescript-eslint/ban-ts-comment': 'warn',
55
+ '@typescript-eslint/no-empty-object-type': 'warn',
56
+ '@typescript-eslint/no-explicit-any': 'warn',
57
+ '@typescript-eslint/no-unused-vars': 'warn',
58
+ /*
59
+ '@typescript-eslint/no-unused-vars': [
60
+ 'warn',
61
+ {
62
+ vars: 'all',
63
+ args: 'after-used',
64
+ ignoreRestSiblings: false,
65
+ argsIgnorePattern: '^_',
66
+ varsIgnorePattern: '^_',
67
+ destructuredArrayIgnorePattern: '^_',
68
+ caughtErrorsIgnorePattern: '^(_|ignore)',
69
+ },
70
+ ],
71
+ */
72
+ },
73
+ },
74
+ {
75
+ ignores: ['.next/'],
76
+ },
77
+ ];
package/oxlint.js ADDED
@@ -0,0 +1,291 @@
1
+ import { fileURLToPath } from 'node:url';
2
+
3
+ /**
4
+ * Shared oxlint configurations of the BOM Repository, the oxlint equivalent of the eslint presets.
5
+ * Generated with @oxlint/migrate from base.js, react.js, next.js and plugin.js, then:
6
+ * - every rule is a warning, as eslint-plugin-only-warn did;
7
+ * - formatting rules (@stylistic) are left to the formatter;
8
+ * - the typescript override applies to every ts file (`**` was missing in the eslint glob).
9
+ *
10
+ * oxlint `extends` only inherits rules, plugins and overrides, so each preset is a complete config:
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * // oxlint.config.ts
15
+ * import { next } from '@websolutespa/eslint-config/oxlint';
16
+ * import { defineConfig } from 'oxlint';
17
+ * export default defineConfig(next);
18
+ * ```
19
+ */
20
+
21
+ // js plugins resolve from the consuming config, which may not depend on the plugin itself
22
+ const resolvePlugin = (name) => fileURLToPath(import.meta.resolve(name));
23
+
24
+ const ignorePatterns = [
25
+ '**/.next/**',
26
+ '**/.rollup.cache/**',
27
+ '**/.turbo/**',
28
+ '**/build/**',
29
+ '**/dist/**',
30
+ 'src/app/(payload)/**',
31
+ ];
32
+
33
+ const baseRules = {
34
+ 'constructor-super': 'warn',
35
+ 'getter-return': 'warn',
36
+ 'no-async-promise-executor': 'warn',
37
+ 'no-case-declarations': 'warn',
38
+ 'no-class-assign': 'warn',
39
+ 'no-compare-neg-zero': 'warn',
40
+ 'no-cond-assign': ['warn', 'always'],
41
+ 'no-const-assign': 'warn',
42
+ 'no-constant-binary-expression': 'warn',
43
+ 'no-constant-condition': 'warn',
44
+ 'no-control-regex': 'warn',
45
+ 'no-debugger': 'warn',
46
+ 'no-delete-var': 'warn',
47
+ 'no-dupe-class-members': 'warn',
48
+ 'no-dupe-else-if': 'warn',
49
+ 'no-dupe-keys': 'warn',
50
+ 'no-duplicate-case': 'warn',
51
+ 'no-empty': 'warn',
52
+ 'no-empty-character-class': 'warn',
53
+ 'no-empty-pattern': 'warn',
54
+ 'no-empty-static-block': 'warn',
55
+ 'no-ex-assign': 'warn',
56
+ 'no-extra-boolean-cast': 'warn',
57
+ 'no-fallthrough': 'warn',
58
+ 'no-func-assign': 'warn',
59
+ 'no-global-assign': 'warn',
60
+ 'no-import-assign': 'warn',
61
+ 'no-invalid-regexp': 'warn',
62
+ 'no-irregular-whitespace': 'warn',
63
+ 'no-loss-of-precision': 'warn',
64
+ 'no-misleading-character-class': 'warn',
65
+ 'no-new-native-nonconstructor': 'warn',
66
+ 'no-nonoctal-decimal-escape': 'warn',
67
+ 'no-obj-calls': 'warn',
68
+ 'no-prototype-builtins': 'warn',
69
+ 'no-redeclare': 'warn',
70
+ 'no-regex-spaces': 'warn',
71
+ 'no-self-assign': 'warn',
72
+ 'no-setter-return': 'warn',
73
+ 'no-shadow-restricted-names': 'warn',
74
+ 'no-sparse-arrays': 'warn',
75
+ 'no-this-before-super': 'warn',
76
+ 'no-unassigned-vars': 'warn',
77
+ 'no-unreachable': 'warn',
78
+ 'no-unsafe-finally': 'warn',
79
+ 'no-unsafe-negation': 'warn',
80
+ 'no-unsafe-optional-chaining': 'warn',
81
+ 'no-unused-labels': 'warn',
82
+ 'no-unused-private-class-members': 'warn',
83
+ 'no-unused-vars': 'warn',
84
+ 'no-useless-backreference': 'warn',
85
+ 'no-useless-catch': 'warn',
86
+ 'no-useless-escape': 'warn',
87
+ 'no-with': 'warn',
88
+ 'preserve-caught-error': 'warn',
89
+ 'require-yield': 'warn',
90
+ 'use-isnan': 'warn',
91
+ 'valid-typeof': 'warn',
92
+ 'no-array-constructor': 'warn',
93
+ 'no-unused-expressions': 'warn',
94
+ 'turbo/no-undeclared-env-vars': 'warn',
95
+ 'no-restricted-imports': [
96
+ 'warn',
97
+ {
98
+ paths: [
99
+ {
100
+ name: 'next/headers',
101
+ message:
102
+ 'Read request data (headers, cookies, draftMode) in the template under src/app and pass it down as an argument.',
103
+ },
104
+ ],
105
+ },
106
+ ],
107
+ 'typescript/ban-ts-comment': 'warn',
108
+ 'typescript/no-duplicate-enum-values': 'warn',
109
+ 'typescript/no-empty-object-type': 'warn',
110
+ 'typescript/no-explicit-any': 'warn',
111
+ 'typescript/no-extra-non-null-assertion': 'warn',
112
+ 'typescript/no-misused-new': 'warn',
113
+ 'typescript/no-namespace': 'warn',
114
+ 'typescript/no-non-null-asserted-optional-chain': 'warn',
115
+ 'typescript/no-require-imports': 'warn',
116
+ 'typescript/no-this-alias': 'warn',
117
+ 'typescript/no-unnecessary-type-constraint': 'warn',
118
+ 'typescript/no-unsafe-declaration-merging': 'warn',
119
+ 'typescript/no-unsafe-function-type': 'warn',
120
+ 'typescript/no-wrapper-object-types': 'warn',
121
+ 'typescript/prefer-as-const': 'warn',
122
+ 'typescript/prefer-namespace-keyword': 'warn',
123
+ 'typescript/triple-slash-reference': 'warn',
124
+ };
125
+
126
+ const overrides = [
127
+ {
128
+ files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],
129
+ rules: {
130
+ 'constructor-super': 'off',
131
+ 'getter-return': 'off',
132
+ 'no-class-assign': 'off',
133
+ 'no-const-assign': 'off',
134
+ 'no-dupe-class-members': 'off',
135
+ 'no-dupe-keys': 'off',
136
+ 'no-func-assign': 'off',
137
+ 'no-import-assign': 'off',
138
+ 'no-new-native-nonconstructor': 'off',
139
+ 'no-obj-calls': 'off',
140
+ 'no-redeclare': 'off',
141
+ 'no-setter-return': 'off',
142
+ 'no-this-before-super': 'off',
143
+ 'no-unsafe-negation': 'off',
144
+ 'no-var': 'warn',
145
+ 'no-with': 'off',
146
+ 'prefer-const': 'warn',
147
+ 'prefer-rest-params': 'warn',
148
+ 'prefer-spread': 'warn',
149
+ },
150
+ },
151
+ {
152
+ files: ['src/app/**', '**/handlers/**', '**/*.test.{ts,tsx}'],
153
+ rules: {
154
+ 'no-restricted-imports': 'off',
155
+ },
156
+ },
157
+ {
158
+ files: ['**/*.{ts,tsx}'],
159
+ rules: {
160
+ 'no-unused-vars': 'warn',
161
+ 'no-use-before-define': [
162
+ 'warn',
163
+ {
164
+ functions: false,
165
+ classes: false,
166
+ variables: true,
167
+ allowNamedExports: false,
168
+ },
169
+ ],
170
+ 'typescript/ban-types': 'off',
171
+ 'typescript/explicit-module-boundary-types': 'off',
172
+ 'typescript/no-empty-interface': 'off',
173
+ 'typescript/no-explicit-any': 'warn',
174
+ 'typescript/no-inferrable-types': 'off',
175
+ // type-aware (oxlint --type-aware): unhandled and misused promises
176
+ 'typescript/await-thenable': 'warn',
177
+ 'typescript/no-floating-promises': 'warn',
178
+ 'typescript/no-misused-promises': 'warn',
179
+ },
180
+ },
181
+ ];
182
+
183
+ const reactRules = {
184
+ 'react/display-name': 'warn',
185
+ 'react/jsx-key': 'warn',
186
+ 'react/jsx-no-comment-textnodes': 'warn',
187
+ 'react/jsx-no-duplicate-props': 'warn',
188
+ 'react/jsx-no-target-blank': 'warn',
189
+ 'react/jsx-no-undef': 'warn',
190
+ 'react/no-children-prop': 'warn',
191
+ 'react/no-danger-with-children': 'warn',
192
+ 'react/no-direct-mutation-state': 'warn',
193
+ 'react/no-find-dom-node': 'warn',
194
+ 'react/no-is-mounted': 'warn',
195
+ 'react/no-render-return-value': 'warn',
196
+ 'react/no-string-refs': 'warn',
197
+ 'react/no-unescaped-entities': 'warn',
198
+ 'react/no-unknown-property': 'warn',
199
+ 'react/rules-of-hooks': 'warn',
200
+ 'react/exhaustive-deps': 'warn',
201
+ 'react/static-components': 'warn',
202
+ 'react/use-memo': 'warn',
203
+ 'react/preserve-manual-memoization': 'warn',
204
+ 'react/incompatible-library': 'warn',
205
+ 'react/immutability': 'warn',
206
+ 'react/globals': 'warn',
207
+ 'react/refs': 'warn',
208
+ 'react/set-state-in-effect': 'warn',
209
+ 'react/error-boundaries': 'warn',
210
+ 'react/purity': 'warn',
211
+ 'react/set-state-in-render': 'warn',
212
+ 'react/unsupported-syntax': 'warn',
213
+ };
214
+
215
+ const nextRules = {
216
+ 'nextjs/google-font-display': 'warn',
217
+ 'nextjs/google-font-preconnect': 'warn',
218
+ 'nextjs/next-script-for-ga': 'warn',
219
+ 'nextjs/no-async-client-component': 'warn',
220
+ 'nextjs/no-before-interactive-script-outside-document': 'warn',
221
+ 'nextjs/no-css-tags': 'warn',
222
+ 'nextjs/no-head-element': 'warn',
223
+ 'nextjs/no-html-link-for-pages': 'warn',
224
+ 'nextjs/no-img-element': 'warn',
225
+ 'nextjs/no-page-custom-font': 'warn',
226
+ 'nextjs/no-styled-jsx-in-document': 'warn',
227
+ 'nextjs/no-sync-scripts': 'warn',
228
+ 'nextjs/no-title-in-document-head': 'warn',
229
+ 'nextjs/no-typos': 'warn',
230
+ 'nextjs/no-unwanted-polyfillio': 'warn',
231
+ 'nextjs/inline-script-id': 'warn',
232
+ 'nextjs/no-assign-module-variable': 'warn',
233
+ 'nextjs/no-document-import-in-page': 'warn',
234
+ 'nextjs/no-duplicate-head': 'warn',
235
+ 'nextjs/no-head-import-in-document': 'warn',
236
+ 'nextjs/no-script-component-in-head': 'warn',
237
+ };
238
+
239
+ /** @type {import('oxlint').OxlintConfig} */
240
+ export const base = {
241
+ plugins: ['unicorn', 'typescript'],
242
+ jsPlugins: [{ name: 'turbo', specifier: resolvePlugin('eslint-plugin-turbo') }],
243
+ categories: { correctness: 'off' },
244
+ env: {
245
+ builtin: true,
246
+ },
247
+ ignorePatterns,
248
+ rules: baseRules,
249
+ overrides,
250
+ };
251
+
252
+ /** @type {import('oxlint').OxlintConfig} */
253
+ export const react = {
254
+ ...base,
255
+ plugins: [...base.plugins, 'react'],
256
+ env: {
257
+ builtin: true,
258
+ browser: true,
259
+ serviceworker: true,
260
+ },
261
+ rules: { ...baseRules, ...reactRules },
262
+ };
263
+
264
+ /** @type {import('oxlint').OxlintConfig} */
265
+ export const next = {
266
+ ...base,
267
+ plugins: [...base.plugins, 'react', 'nextjs'],
268
+ env: {
269
+ builtin: true,
270
+ serviceworker: true,
271
+ },
272
+ ignorePatterns: [...ignorePatterns, '.next/'],
273
+ rules: { ...baseRules, ...reactRules, ...nextRules },
274
+ overrides: overrides.map((o) =>
275
+ o.files.includes('**/*.{ts,tsx}')
276
+ ? {
277
+ ...o,
278
+ rules: {
279
+ ...o.rules,
280
+ ...{
281
+ 'typescript/ban-ts-comment': 'warn',
282
+ 'typescript/no-empty-object-type': 'warn',
283
+ },
284
+ },
285
+ }
286
+ : o
287
+ ),
288
+ };
289
+
290
+ /** @type {import('oxlint').OxlintConfig} */
291
+ export const plugin = react;
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@websolutespa/eslint-config",
3
- "version": "3.1.2",
4
- "description": "Eslint shared config of the BOM Repository",
3
+ "version": "4.0.0-next.6",
4
+ "description": "Eslint and oxlint shared configs of the BOM Repository",
5
5
  "keywords": [
6
6
  "bom",
7
7
  "eslint",
8
8
  "config",
9
- "websolute"
9
+ "websolute",
10
+ "oxlint"
10
11
  ],
11
12
  "license": "MIT",
12
13
  "repository": {
@@ -31,12 +32,21 @@
31
32
  "devDependencies": {
32
33
  "typescript": "6.0.3"
33
34
  },
35
+ "peerDependencies": {
36
+ "oxlint": "^1.89.0"
37
+ },
38
+ "peerDependenciesMeta": {
39
+ "oxlint": {
40
+ "optional": true
41
+ }
42
+ },
34
43
  "main": "./base.js",
35
44
  "exports": {
36
45
  ".": "./base.js",
37
46
  "./base": "./base.js",
38
47
  "./next": "./next.js",
39
48
  "./plugin": "./plugin.js",
40
- "./react": "./react.js"
49
+ "./react": "./react.js",
50
+ "./oxlint": "./oxlint.js"
41
51
  }
42
- }
52
+ }
package/plugin.js CHANGED
@@ -1,24 +1,24 @@
1
- import { react } from './react.js';
2
-
3
- /**
4
- * A custom ESLint configuration for plugins.
5
- *
6
- * @type {import("eslint").Linter.Config[]} */
7
- export const plugin = [
8
- ...react,
9
- {
10
- rules: {
11
- 'no-restricted-exports': 'off',
12
- },
13
- },
14
- {
15
- languageOptions: {
16
- // no type-aware rules are enabled, so no typescript project service is needed
17
- // (it failed on files outside the tsconfig, e.g. tests and eslint.config.js)
18
- parserOptions: {
19
- sourceType: 'module',
20
- ecmaVersion: 'latest',
21
- },
22
- },
23
- },
24
- ];
1
+ import { react } from './react.js';
2
+
3
+ /**
4
+ * A custom ESLint configuration for plugins.
5
+ *
6
+ * @type {import("eslint").Linter.Config[]} */
7
+ export const plugin = [
8
+ ...react,
9
+ {
10
+ rules: {
11
+ 'no-restricted-exports': 'off',
12
+ },
13
+ },
14
+ {
15
+ languageOptions: {
16
+ // no type-aware rules are enabled, so no typescript project service is needed
17
+ // (it failed on files outside the tsconfig, e.g. tests and eslint.config.js)
18
+ parserOptions: {
19
+ sourceType: 'module',
20
+ ecmaVersion: 'latest',
21
+ },
22
+ },
23
+ },
24
+ ];
package/react.js CHANGED
@@ -1,40 +1,40 @@
1
- import { fixupPluginRules } from '@eslint/compat';
2
- import reactPluginSource from 'eslint-plugin-react';
3
- import reactHooksPlugin from 'eslint-plugin-react-hooks';
4
- import globals from 'globals';
5
- import { base } from './base.js';
6
-
7
- // eslint-plugin-react uses context methods removed in eslint 10
8
- const reactPlugin = fixupPluginRules(reactPluginSource);
9
- const reactRecommended = {
10
- ...reactPluginSource.configs.flat.recommended,
11
- plugins: { react: reactPlugin },
12
- };
13
-
14
- /**
15
- * A custom ESLint configuration for libraries that use React.
16
- *
17
- * @type {import("eslint").Linter.Config[]} */
18
- export const react = [
19
- ...base,
20
- reactRecommended,
21
- {
22
- languageOptions: {
23
- ...reactRecommended.languageOptions,
24
- globals: {
25
- ...globals.serviceworker,
26
- ...globals.browser,
27
- },
28
- },
29
- },
30
- {
31
- plugins: {
32
- 'react-hooks': reactHooksPlugin,
33
- },
34
- settings: { react: { version: 'detect' } },
35
- rules: {
36
- ...reactHooksPlugin.configs.recommended.rules,
37
- 'react/react-in-jsx-scope': 'off',
38
- },
39
- },
40
- ];
1
+ import { fixupPluginRules } from '@eslint/compat';
2
+ import reactPluginSource from 'eslint-plugin-react';
3
+ import reactHooksPlugin from 'eslint-plugin-react-hooks';
4
+ import globals from 'globals';
5
+ import { base } from './base.js';
6
+
7
+ // eslint-plugin-react uses context methods removed in eslint 10
8
+ const reactPlugin = fixupPluginRules(reactPluginSource);
9
+ const reactRecommended = {
10
+ ...reactPluginSource.configs.flat.recommended,
11
+ plugins: { react: reactPlugin },
12
+ };
13
+
14
+ /**
15
+ * A custom ESLint configuration for libraries that use React.
16
+ *
17
+ * @type {import("eslint").Linter.Config[]} */
18
+ export const react = [
19
+ ...base,
20
+ reactRecommended,
21
+ {
22
+ languageOptions: {
23
+ ...reactRecommended.languageOptions,
24
+ globals: {
25
+ ...globals.serviceworker,
26
+ ...globals.browser,
27
+ },
28
+ },
29
+ },
30
+ {
31
+ plugins: {
32
+ 'react-hooks': reactHooksPlugin,
33
+ },
34
+ settings: { react: { version: 'detect' } },
35
+ rules: {
36
+ ...reactHooksPlugin.configs.recommended.rules,
37
+ 'react/react-in-jsx-scope': 'off',
38
+ },
39
+ },
40
+ ];