chore
This commit is contained in:
186
src/index.ts
186
src/index.ts
@ -1,21 +1,31 @@
|
||||
/// <reference path="./modules.d.ts" />
|
||||
import './redirect';
|
||||
import { uniq } from 'lodash';
|
||||
import type { Merge, SetRequired } from 'type-fest';
|
||||
import type { Rule } from 'eslint';
|
||||
import type { ESLintUtils } from '@typescript-eslint/utils';
|
||||
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';
|
||||
import type {
|
||||
ESLintConfig,
|
||||
Extends,
|
||||
KnownExtends,
|
||||
Plugin,
|
||||
Rules,
|
||||
Settings,
|
||||
} from '@aet/eslint-define-config';
|
||||
|
||||
import { importTypeScript } from './presets/typescript';
|
||||
import { unicorn } from './presets/unicorn';
|
||||
import { eslintRules } from './presets/eslint';
|
||||
import { reactRules } from './presets/react';
|
||||
import { importRules } from './presets/import-x';
|
||||
import { jsDocRules } from './presets/jsdoc';
|
||||
import { graphqlRules } from './presets/graphql';
|
||||
import { localRules } from './presets/local';
|
||||
import { local } from './presets/local';
|
||||
import { error, warn, off } from './constants';
|
||||
import { tailwindRules } from './presets/tailwind';
|
||||
import { checkEnv } from './env';
|
||||
|
||||
export { graphql } from './presets/graphql';
|
||||
export { jsdoc } from './presets/jsdoc';
|
||||
export { storybook } from './presets/misc';
|
||||
export { react, reactRefresh } from './presets/react';
|
||||
export { tailwind } from './presets/tailwind';
|
||||
|
||||
export { error, warn, off };
|
||||
|
||||
declare global {
|
||||
@ -57,6 +67,8 @@ export interface CustomRule {
|
||||
options?: RuleLevel;
|
||||
}
|
||||
|
||||
export type Middleware = (config: MiddlewareConfig, helpers: MiddlewareFunctions) => void;
|
||||
|
||||
/**
|
||||
* ESLint Configuration.
|
||||
* @see [ESLint Configuration](https://eslint.org/docs/latest/user-guide/configuring/)
|
||||
@ -81,6 +93,27 @@ export type InputConfig = Omit<ESLintConfig, 'rules'> & {
|
||||
auto?: boolean;
|
||||
};
|
||||
|
||||
type OptionalObjectKey<T> = Exclude<
|
||||
{
|
||||
[Key in keyof T]: undefined | any[] extends T[Key]
|
||||
? Key
|
||||
: undefined | Record<any, any> extends T[Key]
|
||||
? Key
|
||||
: never;
|
||||
}[keyof T],
|
||||
undefined
|
||||
>;
|
||||
|
||||
type MiddlewareConfig = Merge<
|
||||
SetRequired<ESLintConfig, OptionalObjectKey<ESLintConfig>>,
|
||||
{ extends: KnownExtends[] }
|
||||
>;
|
||||
|
||||
interface MiddlewareFunctions {
|
||||
addRules(rules: Partial<RuleOptions>): void;
|
||||
addSettings(settings: Partial<Settings>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a ESLint config object.
|
||||
*
|
||||
@ -100,124 +133,75 @@ export type InputConfig = Omit<ESLintConfig, 'rules'> & {
|
||||
* Non bundled:
|
||||
* 1. [`graphql`](https://the-guild.dev/graphql/eslint/rules)
|
||||
*/
|
||||
export function extendConfig(of: InputConfig = {}): ESLintConfig {
|
||||
export function extendConfig(
|
||||
of: InputConfig & {
|
||||
middlewares: Middleware[];
|
||||
} = {
|
||||
middlewares: [],
|
||||
},
|
||||
): ESLintConfig {
|
||||
const {
|
||||
auto,
|
||||
auto = true,
|
||||
plugins: _plugins = [],
|
||||
settings,
|
||||
settings = {},
|
||||
rules,
|
||||
extends: _extends,
|
||||
overrides,
|
||||
customRuleFiles,
|
||||
parserOptions,
|
||||
middlewares: _middlewares = [],
|
||||
// @ts-expect-error
|
||||
localRules: _,
|
||||
...rest
|
||||
} = of;
|
||||
|
||||
let hasReact = false;
|
||||
let plugins: Plugin[] = _plugins;
|
||||
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 middlewares: Middleware[] = uniq([
|
||||
importTypeScript,
|
||||
unicorn,
|
||||
local,
|
||||
...(auto ? checkEnv() : []),
|
||||
..._middlewares,
|
||||
]);
|
||||
|
||||
const hasJsDoc = plugins.includes('jsdoc');
|
||||
const hasGraphQL = plugins.includes('@graphql-eslint');
|
||||
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 result: InputConfig = {
|
||||
const result: MiddlewareConfig = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: unique('@typescript-eslint', 'import-x', 'rules', 'unicorn', plugins),
|
||||
plugins: unique('rules', plugins),
|
||||
env: { node: true, browser: true, es2023: true },
|
||||
reportUnusedDisableDirectives: true,
|
||||
parserOptions: {
|
||||
project: true,
|
||||
...parserOptions,
|
||||
},
|
||||
extends: unique(
|
||||
'eslint:recommended',
|
||||
'prettier',
|
||||
'plugin:@typescript-eslint/recommended-type-checked',
|
||||
'plugin:import-x/errors',
|
||||
'plugin:import-x/typescript',
|
||||
hasReact && [
|
||||
'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',
|
||||
extend as string[],
|
||||
),
|
||||
settings: {
|
||||
'import-x/parsers': {
|
||||
'@typescript-eslint/parser': ['.ts', '.tsx', '.mts', '.cts'],
|
||||
},
|
||||
'import-x/resolver': {
|
||||
typescript: {
|
||||
alwaysTryTypes: true,
|
||||
},
|
||||
},
|
||||
...settings,
|
||||
},
|
||||
ignorePatterns: [],
|
||||
globals: {},
|
||||
extends: ['eslint:recommended', 'prettier', ...(extend as string[])],
|
||||
settings,
|
||||
overrides: [
|
||||
{
|
||||
files: ['.eslintrc.js', '.eslintrc.cjs', '*.config.js', 'index.js'],
|
||||
extends: ['plugin:@typescript-eslint/disable-type-checked'],
|
||||
rules: {
|
||||
'rules/restrict-template-expressions': off,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.d.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/consistent-type-imports': off,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['repl.ts', 'scripts/**/*.ts'],
|
||||
rules: {
|
||||
'no-console': off,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.tsx'],
|
||||
rules: {
|
||||
'@eslint-react/no-leaked-conditional-rendering': error,
|
||||
},
|
||||
},
|
||||
{ files: ['repl.ts', 'scripts/**/*.ts'], rules: { 'no-console': off } },
|
||||
...(overrides ?? []),
|
||||
],
|
||||
rules: {
|
||||
...eslintRules,
|
||||
...typescriptRules,
|
||||
...importRules,
|
||||
...localRules,
|
||||
...(hasReact && reactRules),
|
||||
...(plugins.includes('react-refresh') && {
|
||||
'react-refresh/only-export-components': [warn, { allowConstantExport: true }],
|
||||
}),
|
||||
...unicornRules,
|
||||
...(hasJsDoc && jsDocRules),
|
||||
...(hasGraphQL && graphqlRules),
|
||||
...(hasTailwind && tailwindRules),
|
||||
...rules,
|
||||
},
|
||||
rules: { ...eslintRules, ...rules },
|
||||
...rest,
|
||||
};
|
||||
|
||||
const functions: MiddlewareFunctions = {
|
||||
addRules(newRules) {
|
||||
Object.assign(result.rules, newRules);
|
||||
},
|
||||
addSettings(newSettings) {
|
||||
Object.assign(result.settings, newSettings);
|
||||
},
|
||||
};
|
||||
|
||||
for (const fn of middlewares) {
|
||||
fn(result, functions);
|
||||
}
|
||||
|
||||
result.plugins = unique(result.plugins);
|
||||
result.extends = unique(result.extends);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
Reference in New Issue
Block a user