zeno-config 1.0.3 → 2.1.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
@@ -22,17 +22,14 @@ Install the package and its peer dependencies:
22
22
 
23
23
  ```bash
24
24
  # Using pnpm (recommended)
25
-
26
- # Base dependencies
27
- pnpm add -D zeno-config eslint prettier @eslint/js @stylistic/eslint-plugin eslint-config-prettier eslint-plugin-import-x eslint-plugin-n eslint-plugin-prettier eslint-plugin-unicorn
28
-
29
- # For React projects, also install:
30
- pnpm add -D eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y eslint-plugin-react-you-might-not-need-an-effect
25
+ pnpm add -D zeno-config eslint prettier
31
26
 
32
27
  # For TypeScript projects, also install:
33
- pnpm add -D typescript typescript-eslint
28
+ pnpm add -D typescript
34
29
  ```
35
30
 
31
+ All ESLint plugins are bundled with zeno-config, so you don't need to install them separately.
32
+
36
33
  ## Usage
37
34
 
38
35
  ### ESLint Configuration
@@ -44,23 +41,12 @@ Create an `eslint.config.js` file in your project root:
44
41
  ```javascript
45
42
  import { defineZenoConfig } from 'zeno-config/eslint';
46
43
 
47
- // defineZenoConfig returns a Promise - ESLint 9+ flat config supports this natively
48
44
  export default defineZenoConfig({
49
45
  ts: true, // Enable TypeScript support (default: false)
50
46
  react: true, // Enable React support (default: false)
51
47
  });
52
48
  ```
53
49
 
54
- #### Required: Empty `.eslintrc` File
55
-
56
- You must create an empty `.eslintrc` file in your project root for the `import-x/no-unused-modules` rule to work correctly with flat config:
57
-
58
- ```bash
59
- touch .eslintrc
60
- ```
61
-
62
- This is a workaround for a [known limitation](https://github.com/import-js/eslint-plugin-import/issues/3079) where certain internal ESLint APIs are excluded when using flat config. The file can be empty or contain only `ignorePatterns` if you need to ignore specific files.
63
-
64
50
  #### `engines` field in `package.json`
65
51
 
66
52
  Add an `engines` field to your `package.json` with your supported Node.js versions. Some rules for Node.js use this:
@@ -83,6 +69,9 @@ export default defineZenoConfig(
83
69
  react: true,
84
70
  ts: true,
85
71
 
72
+ // Additional directories to ignore (added to defaults: node_modules, dist, build, coverage)
73
+ ignoreDirs: ['out', '.next'],
74
+
86
75
  // If using .js extensions for React files, specify React directories
87
76
  reactDirs: ['src/client', 'src/components'],
88
77
 
@@ -92,6 +81,12 @@ export default defineZenoConfig(
92
81
  // Patterns to ignore for import/no-unresolved rule
93
82
  ignoreExports: ['^@/'],
94
83
 
84
+ // Additional file patterns to allow dev dependencies in (for no-extraneous-dependencies rule)
85
+ additionalDevDependencies: [
86
+ '**/scripts/**/*.js',
87
+ '**/playwright.config.ts',
88
+ ],
89
+
95
90
  // Extensions to ignore for import/extensions rule
96
91
  extensionsIgnorePattern: {
97
92
  svg: 'always',
@@ -199,15 +194,18 @@ import {
199
194
 
200
195
  ### `defineZenoConfig(options, additionalESLintConfig)`
201
196
 
202
- | Option | Type | Default | Description |
203
- | ------------------------- | ---------- | ----------- | ----------------------------------------------------------------------------------- |
204
- | `react` | `boolean` | `false` | Enable React-specific rules |
205
- | `ts` | `boolean` | `false` | Enable TypeScript-specific rules |
206
- | `reactDirs` | `string[]` | `[]` | Directories containing React files (for projects using .js for both React and Node) |
207
- | `nodeIgnoreDirs` | `string[]` | `[]` | Directories to ignore for Node-specific rules (defaults to `reactDirs` if not set) |
208
- | `ignoreExports` | `string[]` | `[]` | Export patterns to ignore for import/no-unresolved rule |
209
- | `extensionsIgnorePattern` | `object` | `{}` | Extension patterns to ignore for import/extensions rule |
210
- | `webpackConfig` | `string` | `undefined` | Path to webpack config for import resolver |
197
+ | Option | Type | Default | Description |
198
+ | --------------------------- | ---------- | ----------- | --------------------------------------------------------------------------------------------- |
199
+ | `react` | `boolean` | `false` | Enable React-specific rules |
200
+ | `ts` | `boolean` | `false` | Enable TypeScript-specific rules |
201
+ | `performanceMode` | `boolean` | `false` | Disables expensive rules for better performance |
202
+ | `ignoreDirs` | `string[]` | `[]` | Additional directories to ignore (added to defaults: node_modules, dist, build, coverage) |
203
+ | `reactDirs` | `string[]` | `[]` | Directories containing React files (for projects using .js for both React and Node) |
204
+ | `nodeIgnoreDirs` | `string[]` | `[]` | Directories to ignore for Node-specific rules (defaults to `reactDirs` if not set) |
205
+ | `ignoreExports` | `string[]` | `[]` | Export patterns to ignore for import/no-unresolved rule |
206
+ | `additionalDevDependencies` | `string[]` | `[]` | Additional file patterns to allow dev dependencies in (for import/no-extraneous-dependencies) |
207
+ | `extensionsIgnorePattern` | `object` | `{}` | Extension patterns to ignore for import/extensions rule |
208
+ | `webpackConfig` | `string` | `undefined` | Path to webpack config for import resolver |
211
209
 
212
210
  ## Advanced Usage
213
211
 
@@ -220,14 +218,13 @@ import zenoInternals from 'zeno-config/eslint';
220
218
 
221
219
  const { configs, rules, extensions } = zenoInternals;
222
220
 
223
- // Note: getReact() and getTypescript() are async (return Promises)
224
- export default (async () => [
221
+ export default [
225
222
  ...configs.getBase(),
226
223
  ...configs.getNode(),
227
- ...(await configs.getReact()),
228
- ...(await configs.getTypescript()),
224
+ ...configs.getReact(),
225
+ ...configs.getTypescript(),
229
226
  // Your custom configs
230
- ])();
227
+ ];
231
228
  ```
232
229
 
233
230
  ### Accessing Individual Rules
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zeno-config",
3
- "version": "1.0.3",
3
+ "version": "2.1.0",
4
4
  "description": "Preconfigured and opinionated ESLint, Prettier, and TypeScript setup",
5
5
  "author": "Rick Brenn <brenn.rick@gmail.com>",
6
6
  "license": "MIT",
@@ -46,63 +46,38 @@
46
46
  "src/**"
47
47
  ],
48
48
  "peerDependencies": {
49
- "@eslint/js": "^9.39.2",
50
- "@stylistic/eslint-plugin": "^5.6.1",
51
49
  "eslint": "^9.39.2",
52
- "eslint-config-prettier": "^10.1.8",
53
- "eslint-plugin-import-x": "^4.16.1",
54
- "eslint-plugin-jsx-a11y": "^6.10.2",
55
- "eslint-plugin-n": "^17.23.1",
56
- "eslint-plugin-prettier": "^5.5.4",
57
- "eslint-plugin-react": "^7.37.5",
58
- "eslint-plugin-react-hooks": "^7.0.1",
59
- "eslint-plugin-react-you-might-not-need-an-effect": "^0.8.5",
60
- "eslint-plugin-unicorn": "^62.0.0",
61
- "prettier": "^3.7.4",
62
- "typescript": "^5.9.3",
63
- "typescript-eslint": "^8.50.1"
50
+ "prettier": "^3.8.0",
51
+ "typescript": "^5.9.3"
64
52
  },
65
53
  "peerDependenciesMeta": {
66
- "eslint-plugin-jsx-a11y": {
67
- "optional": true
68
- },
69
- "eslint-plugin-react": {
70
- "optional": true
71
- },
72
- "eslint-plugin-react-hooks": {
73
- "optional": true
74
- },
75
- "eslint-plugin-react-you-might-not-need-an-effect": {
76
- "optional": true
77
- },
78
54
  "typescript": {
79
55
  "optional": true
80
- },
81
- "typescript-eslint": {
82
- "optional": true
83
56
  }
84
57
  },
85
58
  "devDependencies": {
86
- "@eslint/js": "9.39.2",
87
- "@stylistic/eslint-plugin": "5.6.1",
88
59
  "eslint": "9.39.2",
60
+ "prettier": "3.8.0",
61
+ "typescript": "5.9.3"
62
+ },
63
+ "dependencies": {
64
+ "@eslint/js": "9.39.2",
65
+ "@stylistic/eslint-plugin": "5.7.0",
89
66
  "eslint-config-prettier": "10.1.8",
67
+ "eslint-import-resolver-webpack": "^0.13.10",
90
68
  "eslint-plugin-import-x": "4.16.1",
91
69
  "eslint-plugin-jsx-a11y": "6.10.2",
92
- "eslint-plugin-n": "17.23.1",
93
- "eslint-plugin-prettier": "5.5.4",
70
+ "eslint-plugin-n": "17.23.2",
71
+ "eslint-plugin-prettier": "5.5.5",
94
72
  "eslint-plugin-react": "7.37.5",
95
73
  "eslint-plugin-react-hooks": "7.0.1",
96
74
  "eslint-plugin-react-you-might-not-need-an-effect": "0.8.5",
97
75
  "eslint-plugin-unicorn": "62.0.0",
98
- "prettier": "3.7.4",
99
- "typescript": "5.9.3",
100
- "typescript-eslint": "8.50.1"
101
- },
102
- "dependencies": {
103
- "globals": "16.5.0"
76
+ "globals": "17.0.0",
77
+ "typescript-eslint": "8.53.1"
104
78
  },
105
79
  "scripts": {
106
- "inspect": "pnpm dlx eslint --inspect-config"
80
+ "inspect": "eslint --inspect-config",
81
+ "lint": "eslint \"**/*.{js,cjs,mjs}\""
107
82
  }
108
83
  }
@@ -3,10 +3,14 @@ import { type Linter } from 'eslint';
3
3
  interface BaseConfigOptions {
4
4
  /** Export patterns to ignore for import rules */
5
5
  ignoreExports?: string[];
6
+ /** Additional file patterns to allow dev dependencies in (for no-extraneous-dependencies rule) */
7
+ additionalDevDependencies?: string[];
6
8
  /** Extension patterns to ignore for import rules */
7
9
  extensionsIgnorePattern?: Record<string, string>;
8
10
  /** Path to webpack config for import resolver */
9
11
  webpackConfig?: string;
12
+ /** Disables expensive rules for performance */
13
+ performanceMode?: boolean;
10
14
  }
11
15
 
12
16
  interface NodeConfigOptions {
@@ -21,17 +25,28 @@ interface ReactConfigOptions {
21
25
  extensionsIgnorePattern?: Record<string, string>;
22
26
  }
23
27
 
28
+ interface TypescriptConfigOptions {
29
+ /** Enable React-specific rules */
30
+ react?: boolean;
31
+ }
32
+
24
33
  interface DefineZenoConfigOptions {
25
34
  /** Enable React-specific rules */
26
35
  react?: boolean;
27
36
  /** Enable TypeScript-specific rules */
28
37
  ts?: boolean;
38
+ /** Disables expensive rules for performance */
39
+ performanceMode?: boolean;
40
+ /** Additional directories to ignore (added to defaults: dist, build) */
41
+ ignoreDirs?: string[];
29
42
  /** Directories containing React files (for projects using .js for both React and Node) */
30
43
  reactDirs?: string[];
31
- /** Directories to ignore for Node-specific rules */
44
+ /** Directories to ignore for Node-specific rules only */
32
45
  nodeIgnoreDirs?: string[];
33
46
  /** Export patterns to ignore for import rules */
34
47
  ignoreExports?: string[];
48
+ /** Additional file patterns to allow dev dependencies in (for no-extraneous-dependencies rule) */
49
+ additionalDevDependencies?: string[];
35
50
  /** Extension patterns to ignore for import rules */
36
51
  extensionsIgnorePattern?: Record<string, string>;
37
52
  /** Path to webpack config for import resolver */
@@ -57,15 +72,16 @@ interface Extensions {
57
72
 
58
73
  interface Configs {
59
74
  getBase: (options?: BaseConfigOptions) => Linter.Config[];
60
- getReact: (options?: ReactConfigOptions) => Promise<Linter.Config[]>;
75
+ getReact: (options?: ReactConfigOptions) => Linter.Config[];
61
76
  getNode: (options?: NodeConfigOptions) => Linter.Config[];
62
- getTypescript: () => Promise<Linter.Config[]>;
77
+ getTypescript: (options?: TypescriptConfigOptions) => Linter.Config[];
63
78
  }
64
79
 
65
80
  interface Rules {
66
81
  getBaseRules: () => Linter.RulesRecord;
67
82
  getImportPluginRules: (options?: {
68
83
  ignoreExports?: string[];
84
+ additionalDevDependencies?: string[];
69
85
  extensionsIgnorePattern?: Record<string, string>;
70
86
  }) => Linter.RulesRecord;
71
87
  getStylisticPluginRules: () => Linter.RulesRecord;
@@ -89,12 +105,9 @@ declare const internals: Internals;
89
105
  /**
90
106
  * Defines a Zeno ESLint configuration.
91
107
  *
92
- * This function is async because React and TypeScript dependencies are loaded
93
- * dynamically (only when enabled) to avoid errors when optional deps aren't installed.
94
- *
95
108
  * @param arg1 - Options object or additional config array. If an array, treated as additional config.
96
109
  * @param arg2 - Additional ESLint config objects to merge (only used if arg1 is options object).
97
- * @returns Promise that resolves to ESLint flat config array.
110
+ * @returns ESLint flat config array.
98
111
  *
99
112
  * @example
100
113
  * // With options object (using default export)
@@ -111,7 +124,7 @@ declare const internals: Internals;
111
124
  declare function defineZenoConfig(
112
125
  arg1?: DefineZenoConfigOptions | Linter.Config[],
113
126
  arg2?: Linter.Config[]
114
- ): Promise<Linter.Config[]>;
127
+ ): Linter.Config[];
115
128
 
116
129
  export {
117
130
  type BaseConfigOptions,
@@ -122,6 +135,7 @@ export {
122
135
  type NodeConfigOptions,
123
136
  type ReactConfigOptions,
124
137
  type Rules,
138
+ type TypescriptConfigOptions,
125
139
  defineZenoConfig,
126
140
  };
127
141
  export default internals;
@@ -6,6 +6,11 @@ import prettierPlugin from 'eslint-plugin-prettier/recommended';
6
6
  import stylisticPlugin from '@stylistic/eslint-plugin';
7
7
  import nodePlugin from 'eslint-plugin-n';
8
8
  import unicornPlugin from 'eslint-plugin-unicorn';
9
+ import reactPlugin from 'eslint-plugin-react';
10
+ import reactHooksPlugin from 'eslint-plugin-react-hooks';
11
+ import jsxA11yPlugin from 'eslint-plugin-jsx-a11y';
12
+ import reactYouMightNotNeedAnEffectPlugin from 'eslint-plugin-react-you-might-not-need-an-effect';
13
+ import typescriptEslint from 'typescript-eslint';
9
14
  import getBaseRules from './rules/baseRules.js';
10
15
  import getImportPluginRules from './rules/importPluginRules.js';
11
16
  import getReactPluginRules from './rules/reactPluginRules.js';
@@ -33,7 +38,7 @@ import {
33
38
  typescriptExtensionsString,
34
39
  } from '../extensions.js';
35
40
 
36
- const ignoreDirs = [
41
+ const defaultIgnoreDirs = [
37
42
  '**/node_modules/*',
38
43
  '**/dist/*',
39
44
  '**/build/*',
@@ -45,8 +50,10 @@ const ignoreDirs = [
45
50
  *
46
51
  * @param {Object} [options={}] - Configuration options.
47
52
  * @param {string[]} [options.ignoreExports] - Export patterns to ignore for import rules.
53
+ * @param {string[]} [options.additionalDevDependencies] - Additional file patterns to allow dev dependencies in (for no-extraneous-dependencies rule).
48
54
  * @param {Object} [options.extensionsIgnorePattern] - Extension patterns to ignore for import rules.
49
55
  * @param {string} [options.webpackConfig] - Path to webpack config for import resolver.
56
+ * @param {boolean} [options.performanceMode=false] - Disables expensive rules for performance.
50
57
  * @returns {Array} ESLint flat config array.
51
58
  */
52
59
  const baseConfig = (options = {}) => {
@@ -54,7 +61,6 @@ const baseConfig = (options = {}) => {
54
61
  {
55
62
  name: 'zeno/base',
56
63
  files: [`**/*{${allExtensionsString}}`],
57
- ignores: [...ignoreDirs],
58
64
  languageOptions: {
59
65
  ecmaVersion: 'latest',
60
66
  sourceType: 'module',
@@ -79,7 +85,10 @@ const baseConfig = (options = {}) => {
79
85
  ...getBaseRules(),
80
86
  ...getImportPluginRules({
81
87
  ignoreExports: options.ignoreExports,
88
+ additionalDevDependencies:
89
+ options.additionalDevDependencies,
82
90
  extensionsIgnorePattern: options.extensionsIgnorePattern,
91
+ performanceMode: options.performanceMode,
83
92
  }),
84
93
  ...getStylisticPluginRules(),
85
94
  ...getUnicornPluginRules(),
@@ -100,7 +109,7 @@ const baseConfig = (options = {}) => {
100
109
  * @returns {Array} ESLint flat config array.
101
110
  */
102
111
  const nodeConfig = (options = {}) => {
103
- let ignores = [...ignoreDirs];
112
+ let ignores = [...defaultIgnoreDirs];
104
113
  if (options.ignoreDirs && options.ignoreDirs.length > 0) {
105
114
  const optionsIgnoreDirs = options.ignoreDirs.map((dir) => {
106
115
  return `${dir}/**/*{${nodeExtensionsString}}`;
@@ -133,22 +142,9 @@ const nodeConfig = (options = {}) => {
133
142
  * @param {Object} [options={}] - Configuration options.
134
143
  * @param {string[]} [options.reactDirs] - Directories containing React files (for projects using .js for both React and Node).
135
144
  * @param {Object} [options.extensionsIgnorePattern] - Extension patterns to ignore for import rules.
136
- * @returns {Promise<Array>} ESLint flat config array.
145
+ * @returns {Array} ESLint flat config array.
137
146
  */
138
- const reactConfig = async (options = {}) => {
139
- // Dynamically import optional React dependencies
140
- const [
141
- { default: reactPlugin },
142
- { default: reactHooksPlugin },
143
- { default: jsxA11yPlugin },
144
- { default: reactYouMightNotNeedAnEffectPlugin },
145
- ] = await Promise.all([
146
- import('eslint-plugin-react'),
147
- import('eslint-plugin-react-hooks'),
148
- import('eslint-plugin-jsx-a11y'),
149
- import('eslint-plugin-react-you-might-not-need-an-effect'),
150
- ]);
151
-
147
+ const reactConfig = (options = {}) => {
152
148
  let files = [`**/*{${reactExtensionsString}}`];
153
149
  let extensions = reactExtensions;
154
150
 
@@ -167,7 +163,6 @@ const reactConfig = async (options = {}) => {
167
163
  {
168
164
  name: 'zeno/react',
169
165
  files,
170
- ignores: [...ignoreDirs],
171
166
  languageOptions: {
172
167
  globals: {
173
168
  ...globals.browser,
@@ -215,13 +210,11 @@ const reactConfig = async (options = {}) => {
215
210
 
216
211
  /**
217
212
  * Creates the TypeScript-specific ESLint configuration.
218
- *
219
- * @returns {Promise<Array>} ESLint flat config array.
213
+ * @param {Object} [options={}] - Configuration options.
214
+ * @param {boolean} [options.react=false] - Enable React-specific rules.
215
+ * @returns {Array} ESLint flat config array.
220
216
  */
221
- const typescriptConfig = async () => {
222
- // Dynamically import optional TypeScript dependencies
223
- const { default: typescriptEslint } = await import('typescript-eslint');
224
-
217
+ const typescriptConfig = (options = {}) => {
225
218
  return [
226
219
  {
227
220
  name: 'zeno/typescript',
@@ -236,10 +229,36 @@ const typescriptConfig = async () => {
236
229
  '@typescript-eslint': typescriptEslint.plugin,
237
230
  },
238
231
  rules: {
239
- ...getTypescriptPluginRules(),
232
+ ...getTypescriptPluginRules({ react: options.react }),
233
+
234
+ // Rules handled by the TypeScript compiler
235
+ 'constructor-super': 'off',
236
+ 'getter-return': 'off',
237
+ 'no-class-assign': 'off',
238
+ 'no-const-assign': 'off',
239
+ 'no-dupe-args': 'off',
240
+ 'no-dupe-keys': 'off',
241
+ 'no-func-assign': 'off',
242
+ 'no-import-assign': 'off',
243
+ 'no-new-native-nonconstructor': 'off',
244
+ 'no-obj-calls': 'off',
245
+ 'no-setter-return': 'off',
246
+ 'no-this-before-super': 'off',
247
+ 'no-undef': 'off',
248
+ 'no-unreachable': 'off',
249
+ 'no-unsafe-negation': 'off',
250
+ 'valid-typeof': 'off',
251
+
252
+ 'import-x/named': 'off',
240
253
 
241
- // other rules the ts compiler handles
242
- 'react/prop-types': 'off',
254
+ ...(options.react
255
+ ? {
256
+ 'react/default-props-match-prop-types': 'off',
257
+ 'react/prop-types': 'off',
258
+ 'react/forbid-foreign-prop-types': 'off',
259
+ 'react/forbid-prop-types': 'off',
260
+ }
261
+ : {}),
243
262
  },
244
263
  },
245
264
  ];
@@ -282,21 +301,22 @@ const internals = {
282
301
  },
283
302
  };
284
303
 
285
- // TODO: make sure to add a suggestion to set the engines fields in package.json
286
-
287
304
  /**
288
305
  * Defines a Zeno ESLint configuration.
289
306
  *
290
307
  * @param {Object|Array} arg1 - Options object or additional config array. If an array, treated as additional config.
291
308
  * @param {boolean} [arg1.react=false] - Enable React-specific rules.
292
309
  * @param {boolean} [arg1.ts=true] - Enable TypeScript-specific rules.
310
+ * @param {boolean} [arg1.performanceMode=false] - Disables expensive rules for performance.
311
+ * @param {string[]} [arg1.ignoreDirs=[]] - Additional directories to ignore (added to defaults: dist, build).
293
312
  * @param {string[]} [arg1.reactDirs=[]] - Directories containing React files (for projects using .js for both React and Node).
294
- * @param {string[]} [arg1.nodeIgnoreDirs=[]] - Directories to ignore for Node-specific rules.
313
+ * @param {string[]} [arg1.nodeIgnoreDirs=[]] - Directories to ignore for Node-specific rules only.
295
314
  * @param {string[]} [arg1.ignoreExports=[]] - Export patterns to ignore for import rules.
315
+ * @param {string[]} [arg1.additionalDevDependencies=[]] - Additional file patterns to allow dev dependencies in (for no-extraneous-dependencies rule).
296
316
  * @param {Object} [arg1.extensionsIgnorePattern={}] - Extension patterns to ignore for import rules.
297
317
  * @param {string} [arg1.webpackConfig] - Path to webpack config for import resolver.
298
318
  * @param {Array} [arg2] - Additional ESLint config objects to merge (only used if arg1 is options object).
299
- * @returns {Promise<Array>} ESLint flat config array.
319
+ * @returns {Array} ESLint flat config array.
300
320
  *
301
321
  * @example
302
322
  * // With options object
@@ -310,16 +330,21 @@ const internals = {
310
330
  * // With config array only
311
331
  * defineZenoConfig([customConfig])
312
332
  */
313
- const defineZenoConfig = async (arg1, arg2) => {
333
+ const defineZenoConfig = (arg1, arg2) => {
314
334
  let options = {
315
335
  react: false,
316
336
  ts: false,
337
+ performanceMode: false,
338
+
339
+ // additional directories to ignore (added to defaults: dist, build)
340
+ ignoreDirs: [],
317
341
 
318
342
  // if a project uses .js file extension for both react and node files this will help separate the rules for each
319
343
  reactDirs: [],
320
344
  nodeIgnoreDirs: [],
321
345
 
322
346
  ignoreExports: [],
347
+ additionalDevDependencies: [],
323
348
  extensionsIgnorePattern: {},
324
349
  webpackConfig: undefined,
325
350
  };
@@ -333,6 +358,9 @@ const defineZenoConfig = async (arg1, arg2) => {
333
358
  }
334
359
 
335
360
  // Ensure array options are arrays
361
+ if (!Array.isArray(options.ignoreDirs)) {
362
+ options.ignoreDirs = [];
363
+ }
336
364
  if (!Array.isArray(options.reactDirs)) {
337
365
  options.reactDirs = [];
338
366
  }
@@ -342,6 +370,9 @@ const defineZenoConfig = async (arg1, arg2) => {
342
370
  if (!Array.isArray(options.ignoreExports)) {
343
371
  options.ignoreExports = [];
344
372
  }
373
+ if (!Array.isArray(options.additionalDevDependencies)) {
374
+ options.additionalDevDependencies = [];
375
+ }
345
376
  if (
346
377
  typeof options.extensionsIgnorePattern !== 'object' ||
347
378
  options.extensionsIgnorePattern === null
@@ -358,24 +389,29 @@ const defineZenoConfig = async (arg1, arg2) => {
358
389
  options.nodeIgnoreDirs = [...options.reactDirs];
359
390
  }
360
391
 
361
- // Load optional configs in parallel if needed
362
- const [reactConfigResult, tsConfigResult] = await Promise.all([
363
- options.react
364
- ? configs.getReact({
365
- reactDirs: options.reactDirs,
366
- extensionsIgnorePattern: options.extensionsIgnorePattern,
367
- })
368
- : Promise.resolve([]),
369
- options.ts ? configs.getTypescript() : Promise.resolve([]),
370
- ]);
392
+ // Load optional configs if needed
393
+ const reactConfigResult = options.react
394
+ ? configs.getReact({
395
+ reactDirs: options.reactDirs,
396
+ extensionsIgnorePattern: options.extensionsIgnorePattern,
397
+ })
398
+ : [];
399
+ const tsConfigResult = options.ts
400
+ ? configs.getTypescript({ react: options.react })
401
+ : [];
371
402
 
372
403
  return defineConfig([
404
+ { ignores: [...defaultIgnoreDirs, ...options.ignoreDirs] },
373
405
  ...configs.getBase({
374
406
  ignoreExports: options.ignoreExports,
407
+ additionalDevDependencies: options.additionalDevDependencies,
375
408
  webpackConfig: options.webpackConfig,
376
409
  extensionsIgnorePattern: options.extensionsIgnorePattern,
410
+ performanceMode: options.performanceMode,
411
+ }),
412
+ ...configs.getNode({
413
+ ignoreDirs: options.nodeIgnoreDirs,
377
414
  }),
378
- ...configs.getNode({ ignoreDirs: options.nodeIgnoreDirs }),
379
415
  ...reactConfigResult,
380
416
  ...tsConfigResult,
381
417
 
@@ -3,14 +3,12 @@ const getBaseRules = () => {
3
3
  // https://eslint.org/docs/latest/rules/array-callback-return
4
4
  'array-callback-return': ['error', { allowImplicit: true }],
5
5
 
6
- // TODO: test this, may only be needed in JS and disabled in TS
7
6
  // https://eslint.org/docs/latest/rules/constructor-super
8
7
  'constructor-super': 'error',
9
8
 
10
9
  // https://eslint.org/docs/latest/rules/for-direction
11
10
  'for-direction': 'error',
12
11
 
13
- // TODO: test this, may only be needed in JS and disabled in TS
14
12
  // https://eslint.org/docs/latest/rules/getter-return
15
13
  'getter-return': ['error', { allowImplicit: true }],
16
14
 
@@ -20,7 +18,6 @@ const getBaseRules = () => {
20
18
  // https://eslint.org/docs/latest/rules/no-await-in-loop
21
19
  'no-await-in-loop': 'warn',
22
20
 
23
- // TODO: test this, may only be needed in JS and disabled in TS
24
21
  // https://eslint.org/docs/latest/rules/no-class-assign
25
22
  'no-class-assign': 'error',
26
23
 
@@ -30,7 +27,6 @@ const getBaseRules = () => {
30
27
  // https://eslint.org/docs/latest/rules/no-cond-assign
31
28
  'no-cond-assign': ['error', 'always'],
32
29
 
33
- // TODO: test this, may only be needed in JS and disabled in TS
34
30
  // https://eslint.org/docs/latest/rules/no-const-assign
35
31
  'no-const-assign': 'error',
36
32
 
@@ -49,18 +45,15 @@ const getBaseRules = () => {
49
45
  // https://eslint.org/docs/latest/rules/no-debugger
50
46
  'no-debugger': 'error',
51
47
 
52
- // TODO: test this, may only be needed in JS and disabled in TS
53
48
  // https://eslint.org/docs/latest/rules/no-dupe-args
54
49
  'no-dupe-args': 'error',
55
50
 
56
- // TODO: test this, may only be needed in JS and disabled in TS
57
51
  // https://eslint.org/docs/latest/rules/no-dupe-class-members
58
52
  'no-dupe-class-members': 'error',
59
53
 
60
54
  // https://eslint.org/docs/latest/rules/no-dupe-else-if
61
55
  'no-dupe-else-if': 'error',
62
56
 
63
- // TODO: test this, may only be needed in JS and disabled in TS
64
57
  // https://eslint.org/docs/latest/rules/no-dupe-keys
65
58
  'no-dupe-keys': 'error',
66
59
 
@@ -82,12 +75,9 @@ const getBaseRules = () => {
82
75
  // https://eslint.org/docs/latest/rules/no-fallthrough
83
76
  'no-fallthrough': 'error',
84
77
 
85
- // TODO: test this, may only be needed in JS and disabled in TS
86
78
  // https://eslint.org/docs/latest/rules/no-func-assign
87
79
  'no-func-assign': 'error',
88
80
 
89
- // may still need this for TS since there is a scenario where you can assign an import to a variable
90
- // TODO: test this, may only be needed in JS and disabled in TS
91
81
  // https://eslint.org/docs/latest/rules/no-import-assign
92
82
  'no-import-assign': 'error',
93
83
 
@@ -106,11 +96,9 @@ const getBaseRules = () => {
106
96
  // https://eslint.org/docs/latest/rules/no-misleading-character-class
107
97
  'no-misleading-character-class': 'error',
108
98
 
109
- // TODO: test this, may only be needed in JS and disabled in TS
110
99
  // https://eslint.org/docs/latest/rules/no-new-native-nonconstructor
111
100
  'no-new-native-nonconstructor': 'error',
112
101
 
113
- // TODO: test this, may only be needed in JS and disabled in TS
114
102
  // https://eslint.org/docs/latest/rules/no-obj-calls
115
103
  'no-obj-calls': 'error',
116
104
 
@@ -126,7 +114,6 @@ const getBaseRules = () => {
126
114
  // https://eslint.org/docs/latest/rules/no-self-compare
127
115
  'no-self-compare': 'error',
128
116
 
129
- // TODO: test this, may only be needed in JS and disabled in TS
130
117
  // https://eslint.org/docs/latest/rules/no-setter-return
131
118
  'no-setter-return': 'error',
132
119
 
@@ -136,14 +123,12 @@ const getBaseRules = () => {
136
123
  // https://eslint.org/docs/latest/rules/no-template-curly-in-string
137
124
  'no-template-curly-in-string': 'error',
138
125
 
139
- // TODO: test this, may only be needed in JS and disabled in TS
140
126
  // https://eslint.org/docs/latest/rules/no-this-before-super
141
127
  'no-this-before-super': 'error',
142
128
 
143
129
  // https://eslint.org/docs/latest/rules/no-unassigned-vars
144
130
  'no-unassigned-vars': 'error',
145
131
 
146
- // TODO: test this, may only be needed in JS and disabled in TS
147
132
  // https://eslint.org/docs/latest/rules/no-undef
148
133
  'no-undef': ['error', { typeof: true }],
149
134
 
@@ -153,7 +138,6 @@ const getBaseRules = () => {
153
138
  // https://eslint.org/docs/latest/rules/no-unmodified-loop-condition
154
139
  'no-unmodified-loop-condition': 'error',
155
140
 
156
- // TODO: test this, may only be needed in JS and disabled in TS (only if allowUnreachableCode: false in config)
157
141
  // https://eslint.org/docs/latest/rules/no-unreachable
158
142
  'no-unreachable': 'error',
159
143
 
@@ -163,7 +147,6 @@ const getBaseRules = () => {
163
147
  // https://eslint.org/docs/latest/rules/no-unsafe-finally
164
148
  'no-unsafe-finally': 'error',
165
149
 
166
- // TODO: test this, may only be needed in JS and disabled in TS
167
150
  // https://eslint.org/docs/latest/rules/no-unsafe-negation
168
151
  'no-unsafe-negation': ['error', { enforceForOrderingRelations: true }],
169
152
 
@@ -232,7 +215,7 @@ const getBaseRules = () => {
232
215
 
233
216
  // https://eslint.org/docs/latest/rules/camelcase
234
217
  camelcase: [
235
- 'error',
218
+ 'warn',
236
219
  {
237
220
  properties: 'always',
238
221
  ignoreDestructuring: false,
@@ -351,7 +334,7 @@ const getBaseRules = () => {
351
334
  'no-array-constructor': 'error',
352
335
 
353
336
  // https://eslint.org/docs/latest/rules/no-bitwise
354
- 'no-bitwise': 'error',
337
+ 'no-bitwise': ['error', { allow: ['~'] }],
355
338
 
356
339
  // https://eslint.org/docs/latest/rules/no-caller
357
340
  'no-caller': 'error',
@@ -651,11 +634,11 @@ const getBaseRules = () => {
651
634
  'error',
652
635
  {
653
636
  VariableDeclarator: {
654
- array: true,
637
+ array: false,
655
638
  object: true,
656
639
  },
657
640
  AssignmentExpression: {
658
- array: true,
641
+ array: false,
659
642
  object: true,
660
643
  },
661
644
  },
@@ -24,6 +24,12 @@ const getImportPluginRules = (options = {}) => {
24
24
  `**/*.stories{${allExtensionsString}}`, // story files
25
25
  `**/.prettierrc{${nodeExtensionsString}}`, // prettier config
26
26
  `**/prettier.config{${nodeExtensionsString}}`, // prettier config
27
+ `**/.babelrc{${nodeExtensionsString}}`, // babel config
28
+ `**/babel.config{${nodeExtensionsString}}`, // babel config
29
+ `**/vite.config{${nodeExtensionsString}}`, // vite config
30
+ `**/vitest.config{${nodeExtensionsString}}`, // vitest config
31
+ `**/vitest.workspace{${nodeExtensionsString}}`, // vitest workspace config
32
+ ...(options.additionalDevDependencies || []),
27
33
  ],
28
34
  optionalDependencies: false,
29
35
  peerDependencies: true,
@@ -43,18 +49,20 @@ const getImportPluginRules = (options = {}) => {
43
49
  'import-x/no-named-as-default-member': 'off',
44
50
 
45
51
  // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-unused-modules.md
46
- 'import-x/no-unused-modules': [
47
- 'warn',
48
- {
49
- missingExports: false,
50
- unusedExports: true,
51
- ignoreUnusedTypeExports: false,
52
- ignoreExports: [
53
- `**/eslint.config{${nodeExtensionsString}}`,
54
- ...(options.ignoreExports || []),
55
- ],
56
- },
57
- ],
52
+ // turning this off until I can iron out all of the false positives
53
+ 'import-x/no-unused-modules': 'off',
54
+ // 'import-x/no-unused-modules': [
55
+ // 'warn',
56
+ // {
57
+ // missingExports: false,
58
+ // unusedExports: true,
59
+ // ignoreUnusedTypeExports: false,
60
+ // ignoreExports: [
61
+ // `**/eslint.config{${nodeExtensionsString}}`,
62
+ // ...(options.ignoreExports || []),
63
+ // ],
64
+ // },
65
+ // ],
58
66
 
59
67
  // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-amd.md
60
68
  'import-x/no-amd': 'error',
@@ -74,7 +82,6 @@ const getImportPluginRules = (options = {}) => {
74
82
  // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/default.md
75
83
  'import-x/default': 'error',
76
84
 
77
- // TODO: test this, may only be needed in JS and disabled in TS
78
85
  // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/named.md
79
86
  'import-x/named': 'error',
80
87
 
@@ -85,7 +92,7 @@ const getImportPluginRules = (options = {}) => {
85
92
  'import-x/no-absolute-path': 'error',
86
93
 
87
94
  // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-cycle.md
88
- 'import-x/no-cycle': 'error',
95
+ 'import-x/no-cycle': options.performanceMode ? 'off' : 'error',
89
96
 
90
97
  // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-dynamic-require.md
91
98
  'import-x/no-dynamic-require': 'error',
@@ -4,13 +4,13 @@ const getReactPluginRules = (options = {}) => {
4
4
  return {
5
5
  // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/boolean-prop-naming.md
6
6
  'react/boolean-prop-naming': [
7
- 'error',
7
+ 'off',
8
8
  {
9
9
  propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'],
10
- rule: '^(is|has|show|can)[A-Z]([A-Za-z0-9]?)+',
10
+ rule: '^(is|has|show|can|allow|should)[A-Z]([A-Za-z0-9]?)+',
11
11
  validateNested: true,
12
12
  message:
13
- 'Boolean prop ({{ propName }}) should start with "is", "has", "show", or "can"',
13
+ 'Boolean prop ({{ propName }}) should start with "is", "has", "show", "can", "allow", or "should"',
14
14
  },
15
15
  ],
16
16
 
@@ -33,7 +33,6 @@ const getReactPluginRules = (options = {}) => {
33
33
  },
34
34
  ],
35
35
 
36
- // TODO: can be disabled in TS
37
36
  // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/default-props-match-prop-types.md
38
37
  'react/default-props-match-prop-types': [
39
38
  'error',
@@ -59,11 +58,9 @@ const getReactPluginRules = (options = {}) => {
59
58
  // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/forbid-elements.md
60
59
  'react/forbid-elements': 'off',
61
60
 
62
- // TODO: can be disabled in TS
63
61
  // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/forbid-foreign-prop-types.md
64
62
  'react/forbid-foreign-prop-types': 'error',
65
63
 
66
- // TODO: can be disabled in TS
67
64
  // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/forbid-prop-types.md
68
65
  'react/forbid-prop-types': [
69
66
  'error',
@@ -213,7 +210,7 @@ const getReactPluginRules = (options = {}) => {
213
210
 
214
211
  // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-leaked-render.md
215
212
  'react/jsx-no-leaked-render': [
216
- 'error',
213
+ 'warn',
217
214
  { validStrategies: ['ternary', 'coerce'] },
218
215
  ],
219
216
 
@@ -441,7 +438,7 @@ const getReactPluginRules = (options = {}) => {
441
438
  'react/self-closing-comp': 'error',
442
439
 
443
440
  // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/sort-comp.md
444
- 'react/sort-comp': 'error',
441
+ 'react/sort-comp': 'off',
445
442
 
446
443
  // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/sort-default-props.md
447
444
  'react/sort-default-props': 'off',
@@ -117,9 +117,6 @@ const getStylisticPluginRules = () => {
117
117
  // https://eslint.style/rules/jsx-self-closing-comp
118
118
  '@stylistic/jsx-self-closing-comp': 'off', // conflicts with react/self-closing-comp
119
119
 
120
- // https://eslint.style/rules/jsx-sort-props
121
- '@stylistic/jsx-sort-props': 'off', // conflicts with react/jsx-sort-props
122
-
123
120
  // https://eslint.style/rules/jsx-tag-spacing
124
121
  '@stylistic/jsx-tag-spacing': 'off', // conflicts with prettier
125
122
 
@@ -49,7 +49,6 @@ const getTypescriptPluginRules = () => {
49
49
  // requires type information
50
50
  '@typescript-eslint/consistent-type-exports': 'off',
51
51
 
52
- // TODO: test this, might conflict with import plugin
53
52
  // https://typescript-eslint.io/rules/consistent-type-imports
54
53
  '@typescript-eslint/consistent-type-imports': 'off',
55
54
 
@@ -79,7 +78,6 @@ const getTypescriptPluginRules = () => {
79
78
  // 'max-params': 'off',
80
79
  '@typescript-eslint/max-params': 'off',
81
80
 
82
- // TODO: test
83
81
  // https://typescript-eslint.io/rules/member-ordering
84
82
  '@typescript-eslint/member-ordering': 'off',
85
83
 
@@ -251,25 +251,25 @@ const getUnicornPluginRules = () => {
251
251
  'unicorn/prefer-array-some': 'warn',
252
252
 
253
253
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-at.md
254
- 'unicorn/prefer-at': 'error',
254
+ 'unicorn/prefer-at': 'warn',
255
255
 
256
256
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-bigint-literals.md
257
- 'unicorn/prefer-bigint-literals': 'error',
257
+ 'unicorn/prefer-bigint-literals': 'warn',
258
258
 
259
259
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-blob-reading-methods.md
260
- 'unicorn/prefer-blob-reading-methods': 'error',
260
+ 'unicorn/prefer-blob-reading-methods': 'warn',
261
261
 
262
262
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-class-fields.md
263
- 'unicorn/prefer-class-fields': 'error',
263
+ 'unicorn/prefer-class-fields': 'warn',
264
264
 
265
265
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-classlist-toggle.md
266
- 'unicorn/prefer-classlist-toggle': 'error',
266
+ 'unicorn/prefer-classlist-toggle': 'warn',
267
267
 
268
268
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-code-point.md
269
- 'unicorn/prefer-code-point': 'error',
269
+ 'unicorn/prefer-code-point': 'warn',
270
270
 
271
271
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-date-now.md
272
- 'unicorn/prefer-date-now': 'error',
272
+ 'unicorn/prefer-date-now': 'warn',
273
273
 
274
274
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-default-parameters.md
275
275
  'unicorn/prefer-default-parameters': 'error',
@@ -305,13 +305,13 @@ const getUnicornPluginRules = () => {
305
305
  'unicorn/prefer-json-parse-buffer': 'off',
306
306
 
307
307
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-keyboard-event-key.md
308
- 'unicorn/prefer-keyboard-event-key': 'error',
308
+ 'unicorn/prefer-keyboard-event-key': 'warn',
309
309
 
310
310
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-logical-operator-over-ternary.md
311
311
  'unicorn/prefer-logical-operator-over-ternary': 'error',
312
312
 
313
313
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-math-min-max.md
314
- 'unicorn/prefer-math-min-max': 'error',
314
+ 'unicorn/prefer-math-min-max': 'warn',
315
315
 
316
316
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-math-trunc.md
317
317
  'unicorn/prefer-math-trunc': 'off',
@@ -320,13 +320,13 @@ const getUnicornPluginRules = () => {
320
320
  'unicorn/prefer-modern-dom-apis': 'warn',
321
321
 
322
322
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-modern-math-apis.md
323
- 'unicorn/prefer-modern-math-apis': 'error',
323
+ 'unicorn/prefer-modern-math-apis': 'warn',
324
324
 
325
325
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-module.md
326
326
  'unicorn/prefer-module': 'error',
327
327
 
328
328
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-native-coercion-functions.md
329
- 'unicorn/prefer-native-coercion-functions': 'error',
329
+ 'unicorn/prefer-native-coercion-functions': 'warn',
330
330
 
331
331
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-negative-index.md
332
332
  'unicorn/prefer-negative-index': 'off',
@@ -335,10 +335,10 @@ const getUnicornPluginRules = () => {
335
335
  'unicorn/prefer-node-protocol': 'warn',
336
336
 
337
337
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-number-properties.md
338
- 'unicorn/prefer-number-properties': 'error',
338
+ 'unicorn/prefer-number-properties': 'warn',
339
339
 
340
340
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-object-from-entries.md
341
- 'unicorn/prefer-object-from-entries': 'error',
341
+ 'unicorn/prefer-object-from-entries': 'warn',
342
342
 
343
343
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-optional-catch-binding.md
344
344
  'unicorn/prefer-optional-catch-binding': 'off',
@@ -350,10 +350,10 @@ const getUnicornPluginRules = () => {
350
350
  'unicorn/prefer-query-selector': 'warn',
351
351
 
352
352
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-reflect-apply.md
353
- 'unicorn/prefer-reflect-apply': 'error',
353
+ 'unicorn/prefer-reflect-apply': 'warn',
354
354
 
355
355
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-regexp-test.md
356
- 'unicorn/prefer-regexp-test': 'error',
356
+ 'unicorn/prefer-regexp-test': 'warn',
357
357
 
358
358
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-response-static-json.md
359
359
  'unicorn/prefer-response-static-json': 'error',
@@ -368,7 +368,7 @@ const getUnicornPluginRules = () => {
368
368
  'unicorn/prefer-single-call': 'error',
369
369
 
370
370
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-spread.md
371
- 'unicorn/prefer-spread': 'error',
371
+ 'unicorn/prefer-spread': 'warn',
372
372
 
373
373
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-raw.md
374
374
  'unicorn/prefer-string-raw': 'off',
@@ -377,13 +377,13 @@ const getUnicornPluginRules = () => {
377
377
  'unicorn/prefer-string-replace-all': 'off',
378
378
 
379
379
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-slice.md
380
- 'unicorn/prefer-string-slice': 'error',
380
+ 'unicorn/prefer-string-slice': 'warn',
381
381
 
382
382
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-starts-ends-with.md
383
383
  'unicorn/prefer-string-starts-ends-with': 'warn',
384
384
 
385
385
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-trim-start-end.md
386
- 'unicorn/prefer-string-trim-start-end': 'error',
386
+ 'unicorn/prefer-string-trim-start-end': 'warn',
387
387
 
388
388
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-structured-clone.md
389
389
  'unicorn/prefer-structured-clone': 'error',
@@ -392,13 +392,13 @@ const getUnicornPluginRules = () => {
392
392
  'unicorn/prefer-switch': 'off',
393
393
 
394
394
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-ternary.md
395
- 'unicorn/prefer-ternary': 'error',
395
+ 'unicorn/prefer-ternary': 'off',
396
396
 
397
397
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-top-level-await.md
398
398
  'unicorn/prefer-top-level-await': 'error',
399
399
 
400
400
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-type-error.md
401
- 'unicorn/prefer-type-error': 'error',
401
+ 'unicorn/prefer-type-error': 'warn',
402
402
 
403
403
  // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prevent-abbreviations.md
404
404
  'unicorn/prevent-abbreviations': 'off',