This commit is contained in:
Alex
2023-11-10 20:29:53 -05:00
parent ee3e7e4203
commit 60b1b8fde3
17 changed files with 539 additions and 128 deletions

View File

@ -1,9 +1,10 @@
import './redirect';
import type { ESLintConfig } from 'eslint-define-config';
import type { ESLintConfig, Rules } from 'eslint-define-config';
import { typescriptRules } from './presets/typescript';
import { unicornRules } from './presets/unicorn';
import { eslintRules } from './presets/eslint';
import { reactRules } from './presets/react';
import { importRules } from './presets/import';
import { error, warn, off } from './constants';
// @ts-expect-error
const { name } = (0, require)('./package.json');
@ -14,12 +15,39 @@ const unique = <T>(arr: T[]): T[] => [...new Set(arr)];
const ensureArray = <T>(value?: T | T[]): T[] =>
value == null ? [] : Array.isArray(value) ? value : [value];
type RuleLevel = 'error' | 'warn' | 'off' | 0 | 1 | 2;
type RuleEntry<Options> = RuleLevel | [RuleLevel, Partial<Options>];
declare module 'eslint-define-config/src/rules/react/no-unknown-property.d.ts' {
export interface NoUnknownPropertyOption {
extends: ('next' | 'emotion')[];
}
}
export interface LocalRuleOptions {
/** Bans import from the specifier '.' and '..' and replaces it with '.+/index' */
'rules/no-import-dot': RuleEntry<unknown>;
/**
* Enforce template literal expressions to be of `string` type
* @see [restrict-template-expressions](https://typescript-eslint.io/rules/restrict-template-expressions)
*/
'rules/restrict-template-expressions': RuleEntry<{ allow: string[] }>;
}
export type RuleOptions = Rules & Partial<LocalRuleOptions>;
/**
* ESLint Configuration.
* @see [ESLint Configuration](https://eslint.org/docs/latest/user-guide/configuring/)
*/
type Config = Omit<ESLintConfig, 'rules'> & {
/**
* Rules.
* @see [Rules](https://eslint.org/docs/latest/user-guide/configuring/rules)
*/
rules?: RuleOptions;
};
/**
* Returns a ESLint config object.
*
@ -33,16 +61,16 @@ export function extendConfig({
extends: _extends,
overrides,
...rest
}: ESLintConfig = {}): ESLintConfig {
}: Config = {}): ESLintConfig {
const hasReact = plugins?.includes('react');
const hasReactRefresh = plugins?.includes('react-refresh');
const hasUnicorn = plugins?.includes('unicorn');
const hasNext = ensureArray(_extends).some(name => name.includes(':@next/next'));
const result: ESLintConfig = {
const result: Config = {
root: true,
parser: '@typescript-eslint/parser',
plugins: unique(['@typescript-eslint', 'import', ...(plugins ?? [])]),
plugins: unique(['@typescript-eslint', 'import', 'rules', ...(plugins ?? [])]),
env: { node: true, browser: true, es2023: true },
reportUnusedDisableDirectives: true,
parserOptions: {
@ -99,9 +127,7 @@ export function extendConfig({
rules: {
...eslintRules,
...typescriptRules,
'import/export': off,
'import/no-duplicates': error,
'import/order': [error, { groups: ['builtin', 'external'] }],
...importRules,
...(hasReact && {
...reactRules,
'react/no-unknown-property': [
@ -113,6 +139,8 @@ export function extendConfig({
'react-refresh/only-export-components': [warn, { allowConstantExport: true }],
}),
...(hasUnicorn && unicornRules),
'rules/no-import-dot': error,
'rules/restrict-template-expressions': error,
...rules,
},
...rest,