This commit is contained in:
Alex
2024-07-27 22:45:56 -04:00
parent 1e6d679af3
commit 2853da4344
26 changed files with 1244 additions and 2704 deletions

View File

@ -1,9 +1,8 @@
/// <reference path="./modules.d.ts" />
import './redirect';
import fs from 'node:fs';
import type { Rule } from 'eslint';
import type { ESLintUtils } from '@typescript-eslint/utils';
import type { ESLintConfig, Rules } from '@aet/eslint-define-config';
import type { ESLintConfig, Extends, Plugin, Rules } from '@aet/eslint-define-config';
// import findCacheDirectory from 'find-cache-dir';
import { typescriptRules } from './presets/typescript';
import { unicornRules } from './presets/unicorn';
@ -15,6 +14,7 @@ import { graphqlRules } from './presets/graphql';
import { localRules } from './presets/local';
import { error, warn, off } from './constants';
import { tailwindRules } from './presets/tailwind';
import { checkEnv } from './env';
export { error, warn, off };
@ -74,12 +74,17 @@ export type InputConfig = Omit<ESLintConfig, 'rules'> & {
* this is statically analyzed.
*/
customRuleFiles?: string | string[];
/**
* Automatically detect project types, dependencies and deduct the plugins.
*/
auto?: boolean;
};
/**
* Returns a ESLint config object.
*
* By default, it includes `["@typescript-eslint", "import", "prettier"]` configs.
* By default, it includes `["@typescript-eslint", "import-x", "prettier", "unicorn"]` configs.
* Additional bundled plugins include:
*
* 1. [`react`](https://github.com/jsx-eslint/eslint-plugin-react#list-of-supported-rules)
@ -88,7 +93,8 @@ export type InputConfig = Omit<ESLintConfig, 'rules'> & {
* 2. [`react-refresh`](https://github.com/ArnaudBarre/eslint-plugin-react-refresh)
* 3. [`jsx-a11y`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y#supported-rules)
* 4. [`unicorn`](https://github.com/sindresorhus/eslint-plugin-unicorn#rules)
* 5. [`n`](https://github.com/eslint-community/eslint-plugin-n#-rules) (Node.js specific)
* 5. [`n`](https://github.com/eslint-community/eslint-plugin-n#-rules) (Node.js specific,
* requires `minimatch`)
* 6. [`jsdoc`](https://github.com/gajus/eslint-plugin-jsdoc#rules)
*
* Non bundled:
@ -96,41 +102,49 @@ export type InputConfig = Omit<ESLintConfig, 'rules'> & {
*/
export function extendConfig(of: InputConfig = {}): ESLintConfig {
const {
plugins = [],
auto,
plugins: _plugins = [],
settings,
rules,
extends: _extends,
overrides,
customRuleFiles,
parserOptions,
// @ts-expect-error
localRules: _,
...rest
} = of;
const hasReact = plugins.includes('react');
const hasReactRefresh = plugins.includes('react-refresh');
const hasUnicorn = plugins.includes('unicorn');
let hasReact = false;
let plugins: Plugin[] = _plugins;
let extend: Extends[] = ensureArray(_extends);
if (auto) {
const env = checkEnv();
hasReact = env.react;
plugins = [..._plugins, ...env.plugins];
extend = [...extend, ...env.extends];
}
const hasJsDoc = plugins.includes('jsdoc');
const hasGraphQL = plugins.includes('@graphql-eslint');
const hasNext = ensureArray(_extends).some(name => name.includes(':@next/next'));
const hasTailwind = ensureArray(_extends).some(name =>
name.includes('plugin:tailwindcss/'),
);
const hasTailwind = extend.some(name => name.includes('plugin:tailwindcss/'));
const ruleDir = false; // ?? findCacheDirectory({ name: '_eslint-rules' });
if (ruleDir) {
fs.rmSync(ruleDir, { recursive: true, force: true });
fs.mkdirSync(ruleDir, { recursive: true });
}
// const ruleDir = false; // ?? findCacheDirectory({ name: '_eslint-rules' });
// if (ruleDir) {
// fs.rmSync(ruleDir, { recursive: true, force: true });
// fs.mkdirSync(ruleDir, { recursive: true });
// }
const result: InputConfig = {
root: true,
parser: '@typescript-eslint/parser',
plugins: unique('@typescript-eslint', 'import-x', 'rules', plugins),
plugins: unique('@typescript-eslint', 'import-x', 'rules', 'unicorn', plugins),
env: { node: true, browser: true, es2023: true },
reportUnusedDisableDirectives: true,
parserOptions: {
project: true,
...parserOptions,
},
extends: unique(
'eslint:recommended',
@ -139,13 +153,14 @@ export function extendConfig(of: InputConfig = {}): ESLintConfig {
'plugin:import-x/errors',
'plugin:import-x/typescript',
hasReact && [
'plugin:react/recommended',
'plugin:@eslint-react/recommended-legacy',
'plugin:@eslint-react/dom-legacy',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
],
hasJsDoc && 'plugin:jsdoc/recommended-typescript',
hasGraphQL && 'plugin:@graphql-eslint/recommended',
_extends,
extend as string[],
),
settings: {
'import-x/parsers': {
@ -156,9 +171,6 @@ export function extendConfig(of: InputConfig = {}): ESLintConfig {
alwaysTryTypes: true,
},
},
react: {
version: 'detect',
},
...settings,
},
overrides: [
@ -181,6 +193,12 @@ export function extendConfig(of: InputConfig = {}): ESLintConfig {
'no-console': off,
},
},
{
files: ['*.tsx'],
rules: {
'@eslint-react/no-leaked-conditional-rendering': error,
},
},
...(overrides ?? []),
],
rules: {
@ -188,17 +206,11 @@ export function extendConfig(of: InputConfig = {}): ESLintConfig {
...typescriptRules,
...importRules,
...localRules,
...(hasReact && {
...reactRules,
'react/no-unknown-property': [
error,
{ ignore: hasNext ? ['css', 'next'] : ['css'] },
],
}),
...(hasReactRefresh && {
...(hasReact && reactRules),
...(plugins.includes('react-refresh') && {
'react-refresh/only-export-components': [warn, { allowConstantExport: true }],
}),
...(hasUnicorn && unicornRules),
...unicornRules,
...(hasJsDoc && jsDocRules),
...(hasGraphQL && graphqlRules),
...(hasTailwind && tailwindRules),