chore
This commit is contained in:
18
.eslintrc
18
.eslintrc
@ -3,12 +3,12 @@
|
|||||||
"env": {
|
"env": {
|
||||||
"node": true,
|
"node": true,
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"es6": true
|
"es6": true,
|
||||||
},
|
},
|
||||||
"extends": ["eslint:recommended", "prettier"],
|
"extends": ["eslint:recommended", "prettier"],
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"sourceType": "module",
|
"sourceType": "module",
|
||||||
"ecmaVersion": "latest"
|
"ecmaVersion": "latest",
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-restricted-imports": [
|
"no-restricted-imports": [
|
||||||
@ -24,14 +24,14 @@
|
|||||||
"object.hasown",
|
"object.hasown",
|
||||||
"object.values",
|
"object.values",
|
||||||
"string.prototype.matchall",
|
"string.prototype.matchall",
|
||||||
"has"
|
"has",
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
"arrow-body-style": ["error", "as-needed"],
|
"arrow-body-style": ["error", "as-needed"],
|
||||||
"class-methods-use-this": [
|
"class-methods-use-this": [
|
||||||
"warn",
|
"warn",
|
||||||
{ "exceptMethods": ["toString", "shouldComponentUpdate"] }
|
{ "exceptMethods": ["toString", "shouldComponentUpdate"] },
|
||||||
],
|
],
|
||||||
"complexity": ["warn", { "max": 100 }],
|
"complexity": ["warn", { "max": 100 }],
|
||||||
"curly": ["error", "multi-line", "consistent"],
|
"curly": ["error", "multi-line", "consistent"],
|
||||||
@ -50,13 +50,13 @@
|
|||||||
"prefer-const": ["error", { "destructuring": "all" }],
|
"prefer-const": ["error", { "destructuring": "all" }],
|
||||||
"prefer-destructuring": [
|
"prefer-destructuring": [
|
||||||
"warn",
|
"warn",
|
||||||
{ "AssignmentExpression": { "array": false, "object": false } }
|
{ "AssignmentExpression": { "array": false, "object": false } },
|
||||||
],
|
],
|
||||||
"prefer-rest-params": "warn",
|
"prefer-rest-params": "warn",
|
||||||
"prefer-spread": "warn",
|
"prefer-spread": "warn",
|
||||||
"quote-props": ["error", "as-needed"],
|
"quote-props": ["error", "as-needed"],
|
||||||
"spaced-comment": ["error", "always", { "markers": ["/"] }],
|
"spaced-comment": ["error", "always", { "markers": ["/"] }],
|
||||||
"sort-imports": ["warn", { "ignoreDeclarationSort": true }],
|
"sort-imports": ["warn", { "ignoreDeclarationSort": true }],
|
||||||
"yoda": ["error", "never", { "exceptRange": true }]
|
"yoda": ["error", "never", { "exceptRange": true }],
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
24
dist/index.d.ts
vendored
24
dist/index.d.ts
vendored
@ -1,12 +1,19 @@
|
|||||||
// Generated by dts-bundle-generator v9.4.0
|
// Generated by dts-bundle-generator v9.4.0
|
||||||
|
|
||||||
import { ESLintConfig, Rules } from '@aet/eslint-define-config';
|
import { ESLintConfig, KnownExtends, Rules, Settings } from '@aet/eslint-define-config';
|
||||||
import { ESLintUtils } from '@typescript-eslint/utils';
|
import { ESLintUtils } from '@typescript-eslint/utils';
|
||||||
import { Rule } from 'eslint';
|
import { Rule } from 'eslint';
|
||||||
|
import { Merge, SetRequired } from 'type-fest';
|
||||||
|
|
||||||
export declare const error = "error";
|
export declare const error = "error";
|
||||||
export declare const warn = "warn";
|
export declare const warn = "warn";
|
||||||
export declare const off = "off";
|
export declare const off = "off";
|
||||||
|
export declare const graphql: Middleware;
|
||||||
|
export declare const jsdoc: Middleware;
|
||||||
|
export declare const storybook: Middleware;
|
||||||
|
export declare const react: Middleware;
|
||||||
|
export declare const reactRefresh: Middleware;
|
||||||
|
export declare const tailwind: Middleware;
|
||||||
export type RuleLevel = "error" | "warn" | "off" | 0 | 1 | 2;
|
export type RuleLevel = "error" | "warn" | "off" | 0 | 1 | 2;
|
||||||
export type RuleEntry<Options> = RuleLevel | [
|
export type RuleEntry<Options> = RuleLevel | [
|
||||||
RuleLevel,
|
RuleLevel,
|
||||||
@ -32,6 +39,7 @@ export interface CustomRule {
|
|||||||
}>;
|
}>;
|
||||||
options?: RuleLevel;
|
options?: RuleLevel;
|
||||||
}
|
}
|
||||||
|
export type Middleware = (config: MiddlewareConfig, helpers: MiddlewareFunctions) => void;
|
||||||
/**
|
/**
|
||||||
* ESLint Configuration.
|
* ESLint Configuration.
|
||||||
* @see [ESLint Configuration](https://eslint.org/docs/latest/user-guide/configuring/)
|
* @see [ESLint Configuration](https://eslint.org/docs/latest/user-guide/configuring/)
|
||||||
@ -53,6 +61,16 @@ export type InputConfig = Omit<ESLintConfig, "rules"> & {
|
|||||||
*/
|
*/
|
||||||
auto?: boolean;
|
auto?: boolean;
|
||||||
};
|
};
|
||||||
|
export 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>;
|
||||||
|
export type MiddlewareConfig = Merge<SetRequired<ESLintConfig, OptionalObjectKey<ESLintConfig>>, {
|
||||||
|
extends: KnownExtends[];
|
||||||
|
}>;
|
||||||
|
export interface MiddlewareFunctions {
|
||||||
|
addRules(rules: Partial<RuleOptions>): void;
|
||||||
|
addSettings(settings: Partial<Settings>): void;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Returns a ESLint config object.
|
* Returns a ESLint config object.
|
||||||
*
|
*
|
||||||
@ -72,6 +90,8 @@ export type InputConfig = Omit<ESLintConfig, "rules"> & {
|
|||||||
* Non bundled:
|
* Non bundled:
|
||||||
* 1. [`graphql`](https://the-guild.dev/graphql/eslint/rules)
|
* 1. [`graphql`](https://the-guild.dev/graphql/eslint/rules)
|
||||||
*/
|
*/
|
||||||
export declare function extendConfig(of?: InputConfig): ESLintConfig;
|
export declare function extendConfig(of?: InputConfig & {
|
||||||
|
middlewares: Middleware[];
|
||||||
|
}): ESLintConfig;
|
||||||
|
|
||||||
export {};
|
export {};
|
||||||
|
4
dist/package.json
vendored
4
dist/package.json
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@aet/eslint-rules",
|
"name": "@aet/eslint-rules",
|
||||||
"version": "1.0.1-beta.10",
|
"version": "1.0.1-beta.11",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nolyfill/is-core-module": "^1.0.39",
|
"@nolyfill/is-core-module": "^1.0.39",
|
||||||
"@aet/eslint-define-config": "0.1.0-beta.10",
|
"@aet/eslint-define-config": "^0.1.0-beta.15",
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
"@tanstack/eslint-plugin-query": "^5.51.15",
|
"@tanstack/eslint-plugin-query": "^5.51.15",
|
||||||
"@types/eslint": "^8.56.11",
|
"@types/eslint": "^8.56.11",
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@aet/eslint-define-config": "^0.1.0-beta.10",
|
"@aet/eslint-define-config": "^0.1.0-beta.15",
|
||||||
"@babel/core": "^7.24.9",
|
"@babel/core": "^7.24.9",
|
||||||
"@babel/plugin-transform-flow-strip-types": "^7.24.7",
|
"@babel/plugin-transform-flow-strip-types": "^7.24.7",
|
||||||
"@babel/preset-env": "^7.25.0",
|
"@babel/preset-env": "^7.25.0",
|
||||||
@ -43,6 +43,7 @@
|
|||||||
"picocolors": "^1.0.1",
|
"picocolors": "^1.0.1",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
|
"type-fest": "^4.23.0",
|
||||||
"typescript": "^5.5.4"
|
"typescript": "^5.5.4"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
|
19
pnpm-lock.yaml
generated
19
pnpm-lock.yaml
generated
@ -22,8 +22,8 @@ importers:
|
|||||||
.:
|
.:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@aet/eslint-define-config':
|
'@aet/eslint-define-config':
|
||||||
specifier: ^0.1.0-beta.10
|
specifier: ^0.1.0-beta.15
|
||||||
version: 0.1.0-beta.10
|
version: 0.1.0-beta.15
|
||||||
'@babel/core':
|
'@babel/core':
|
||||||
specifier: ^7.24.9
|
specifier: ^7.24.9
|
||||||
version: 7.24.9
|
version: 7.24.9
|
||||||
@ -129,6 +129,9 @@ importers:
|
|||||||
prop-types:
|
prop-types:
|
||||||
specifier: ^15.8.1
|
specifier: ^15.8.1
|
||||||
version: 15.8.1
|
version: 15.8.1
|
||||||
|
type-fest:
|
||||||
|
specifier: ^4.23.0
|
||||||
|
version: 4.23.0
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.5.4
|
specifier: ^5.5.4
|
||||||
version: 5.5.4
|
version: 5.5.4
|
||||||
@ -139,8 +142,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
|
resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
'@aet/eslint-define-config@0.1.0-beta.10':
|
'@aet/eslint-define-config@0.1.0-beta.15':
|
||||||
resolution: {integrity: sha512-YTm+DdRvCPMMN+R3PZxJsBLYwUscxIpBhlpo2hSS/KEXtOiNUTGPIdzUERFkdNA1PayYfCDwh4dquKX3IZ0uwQ==}
|
resolution: {integrity: sha512-WQuQyKU4V4RSZi0ShPpBE0LB8+evUjLr34T9XLWDTFJBrVkD6tJXdj8eQlzEWkp8ZxQrPGbYfkegwGHQ1NdLXg==}
|
||||||
engines: {node: '>=18.0.0', npm: '>=9.0.0'}
|
engines: {node: '>=18.0.0', npm: '>=9.0.0'}
|
||||||
|
|
||||||
'@ampproject/remapping@2.2.1':
|
'@ampproject/remapping@2.2.1':
|
||||||
@ -1935,6 +1938,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
|
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
type-fest@4.23.0:
|
||||||
|
resolution: {integrity: sha512-ZiBujro2ohr5+Z/hZWHESLz3g08BBdrdLMieYFULJO+tWc437sn8kQsWLJoZErY8alNhxre9K4p3GURAG11n+w==}
|
||||||
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
typescript@5.5.4:
|
typescript@5.5.4:
|
||||||
resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
|
resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
@ -2022,7 +2029,7 @@ snapshots:
|
|||||||
|
|
||||||
'@aashutoshrathi/word-wrap@1.2.6': {}
|
'@aashutoshrathi/word-wrap@1.2.6': {}
|
||||||
|
|
||||||
'@aet/eslint-define-config@0.1.0-beta.10': {}
|
'@aet/eslint-define-config@0.1.0-beta.15': {}
|
||||||
|
|
||||||
'@ampproject/remapping@2.2.1':
|
'@ampproject/remapping@2.2.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -4018,6 +4025,8 @@ snapshots:
|
|||||||
|
|
||||||
type-fest@0.20.2: {}
|
type-fest@0.20.2: {}
|
||||||
|
|
||||||
|
type-fest@4.23.0: {}
|
||||||
|
|
||||||
typescript@5.5.4: {}
|
typescript@5.5.4: {}
|
||||||
|
|
||||||
undici-types@5.26.5: {}
|
undici-types@5.26.5: {}
|
||||||
|
@ -23,5 +23,4 @@ pull() {
|
|||||||
pull import-js eslint-import-resolver-typescript
|
pull import-js eslint-import-resolver-typescript
|
||||||
pull jsx-eslint eslint-plugin-jsx-a11y
|
pull jsx-eslint eslint-plugin-jsx-a11y
|
||||||
pull eslint-community eslint-plugin-n
|
pull eslint-community eslint-plugin-n
|
||||||
pull jsx-eslint eslint-plugin-react
|
|
||||||
pull jsx-eslint jsx-ast-utils
|
pull jsx-eslint jsx-ast-utils
|
||||||
|
@ -18,10 +18,10 @@
|
|||||||
"subject": "[readme] fix typo in shareable config section in readme"
|
"subject": "[readme] fix typo in shareable config section in readme"
|
||||||
},
|
},
|
||||||
"eslint-plugin-n": {
|
"eslint-plugin-n": {
|
||||||
"hash": "5aad5f1c419b3143ffb9356bd299fc50dc576ee5",
|
"hash": "6744257b43560181412a76eadeb7de564b886ad4",
|
||||||
"date": "2024-07-26T10:04:35+08:00",
|
"date": "2024-07-26T11:46:54+01:00",
|
||||||
"committer": "GitHub",
|
"committer": "GitHub",
|
||||||
"subject": "chore(master): release 17.10.0 (#305)"
|
"subject": "chore(master): release 17.10.1 (#319)"
|
||||||
},
|
},
|
||||||
"eslint-plugin-react": {
|
"eslint-plugin-react": {
|
||||||
"hash": "983b88dd3cb5e07919517d3fde4085f60883ded7",
|
"hash": "983b88dd3cb5e07919517d3fde4085f60883ded7",
|
||||||
|
45
src/env.ts
45
src/env.ts
@ -1,46 +1,39 @@
|
|||||||
import type { Extends, Plugin } from '@aet/eslint-define-config';
|
|
||||||
import * as fs from 'node:fs';
|
import * as fs from 'node:fs';
|
||||||
import { resolve } from 'node:path';
|
import { resolve } from 'node:path';
|
||||||
|
import { Middleware, storybook } from './index';
|
||||||
|
import { react, reactRefresh } from './presets/react';
|
||||||
|
import { tailwind } from './presets/tailwind';
|
||||||
|
import { reactQuery } from './presets/misc';
|
||||||
|
|
||||||
export function checkEnv() {
|
export function* checkEnv(): Generator<Middleware> {
|
||||||
const rootDir = process.cwd();
|
const rootDir = process.cwd();
|
||||||
const plugins: Plugin[] = [];
|
|
||||||
const extend: Extends[] = [];
|
|
||||||
|
|
||||||
const pkgJsonPath = resolve(rootDir, 'package.json');
|
const pkgJsonPath = resolve(rootDir, 'package.json');
|
||||||
const pkgJson = fs.existsSync(pkgJsonPath)
|
const pkgJson = fs.existsSync(pkgJsonPath)
|
||||||
? JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'))
|
? JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'))
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
const deps = Object.keys({
|
const deps = new Set(
|
||||||
|
Object.keys({
|
||||||
...pkgJson.dependencies,
|
...pkgJson.dependencies,
|
||||||
...pkgJson.devDependencies,
|
...pkgJson.devDependencies,
|
||||||
...pkgJson.peerDependencies,
|
...pkgJson.peerDependencies,
|
||||||
});
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
const hasReact = deps.includes('react');
|
if (deps.has('react')) {
|
||||||
if (hasReact) {
|
yield react;
|
||||||
plugins.push('react-hooks');
|
|
||||||
}
|
}
|
||||||
if (deps.includes('@vitejs/plugin-react')) {
|
if (deps.has('@vitejs/plugin-react') && deps.has('eslint-plugin-react-refresh')) {
|
||||||
plugins.push('react-refresh');
|
yield reactRefresh;
|
||||||
}
|
}
|
||||||
|
if (deps.has('tailwindcss') && deps.has('eslint-plugin-tailwindcss')) {
|
||||||
if (deps.includes('tailwindcss') && deps.includes('eslint-plugin-tailwindcss')) {
|
yield tailwind;
|
||||||
plugins.push('tailwindcss');
|
|
||||||
}
|
}
|
||||||
|
if (deps.has('storybook') && deps.has('eslint-plugin-storybook')) {
|
||||||
if (deps.includes('storybook') && deps.includes('eslint-plugin-storybook')) {
|
yield storybook;
|
||||||
extend.push('plugin:storybook/recommended');
|
|
||||||
}
|
}
|
||||||
|
if (deps.has('@tanstack/react-query') && deps.has('@tanstack/eslint-plugin-query')) {
|
||||||
if (deps.includes('@tanstack/react-query')) {
|
yield reactQuery;
|
||||||
extend.push('plugin:@tanstack/eslint-plugin-query/recommended');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
react: hasReact,
|
|
||||||
plugins,
|
|
||||||
extends: extend,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
186
src/index.ts
186
src/index.ts
@ -1,21 +1,31 @@
|
|||||||
/// <reference path="./modules.d.ts" />
|
/// <reference path="./modules.d.ts" />
|
||||||
import './redirect';
|
import './redirect';
|
||||||
|
import { uniq } from 'lodash';
|
||||||
|
import type { Merge, SetRequired } from 'type-fest';
|
||||||
import type { Rule } from 'eslint';
|
import type { Rule } from 'eslint';
|
||||||
import type { ESLintUtils } from '@typescript-eslint/utils';
|
import type { ESLintUtils } from '@typescript-eslint/utils';
|
||||||
import type { ESLintConfig, Extends, Plugin, Rules } from '@aet/eslint-define-config';
|
import type {
|
||||||
// import findCacheDirectory from 'find-cache-dir';
|
ESLintConfig,
|
||||||
import { typescriptRules } from './presets/typescript';
|
Extends,
|
||||||
import { unicornRules } from './presets/unicorn';
|
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 { eslintRules } from './presets/eslint';
|
||||||
import { reactRules } from './presets/react';
|
import { local } from './presets/local';
|
||||||
import { importRules } from './presets/import-x';
|
|
||||||
import { jsDocRules } from './presets/jsdoc';
|
|
||||||
import { graphqlRules } from './presets/graphql';
|
|
||||||
import { localRules } from './presets/local';
|
|
||||||
import { error, warn, off } from './constants';
|
import { error, warn, off } from './constants';
|
||||||
import { tailwindRules } from './presets/tailwind';
|
|
||||||
import { checkEnv } from './env';
|
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 };
|
export { error, warn, off };
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@ -57,6 +67,8 @@ export interface CustomRule {
|
|||||||
options?: RuleLevel;
|
options?: RuleLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Middleware = (config: MiddlewareConfig, helpers: MiddlewareFunctions) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ESLint Configuration.
|
* ESLint Configuration.
|
||||||
* @see [ESLint Configuration](https://eslint.org/docs/latest/user-guide/configuring/)
|
* @see [ESLint Configuration](https://eslint.org/docs/latest/user-guide/configuring/)
|
||||||
@ -81,6 +93,27 @@ export type InputConfig = Omit<ESLintConfig, 'rules'> & {
|
|||||||
auto?: boolean;
|
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.
|
* Returns a ESLint config object.
|
||||||
*
|
*
|
||||||
@ -100,124 +133,75 @@ export type InputConfig = Omit<ESLintConfig, 'rules'> & {
|
|||||||
* Non bundled:
|
* Non bundled:
|
||||||
* 1. [`graphql`](https://the-guild.dev/graphql/eslint/rules)
|
* 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 {
|
const {
|
||||||
auto,
|
auto = true,
|
||||||
plugins: _plugins = [],
|
plugins: _plugins = [],
|
||||||
settings,
|
settings = {},
|
||||||
rules,
|
rules,
|
||||||
extends: _extends,
|
extends: _extends,
|
||||||
overrides,
|
overrides,
|
||||||
customRuleFiles,
|
customRuleFiles,
|
||||||
parserOptions,
|
parserOptions,
|
||||||
|
middlewares: _middlewares = [],
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
localRules: _,
|
localRules: _,
|
||||||
...rest
|
...rest
|
||||||
} = of;
|
} = of;
|
||||||
|
|
||||||
let hasReact = false;
|
let plugins: Plugin[] = [..._plugins];
|
||||||
let plugins: Plugin[] = _plugins;
|
|
||||||
let extend: Extends[] = ensureArray(_extends);
|
let extend: Extends[] = ensureArray(_extends);
|
||||||
|
|
||||||
if (auto) {
|
const middlewares: Middleware[] = uniq([
|
||||||
const env = checkEnv();
|
importTypeScript,
|
||||||
hasReact = env.react;
|
unicorn,
|
||||||
plugins = [..._plugins, ...env.plugins];
|
local,
|
||||||
extend = [...extend, ...env.extends];
|
...(auto ? checkEnv() : []),
|
||||||
}
|
..._middlewares,
|
||||||
|
]);
|
||||||
|
|
||||||
const hasJsDoc = plugins.includes('jsdoc');
|
const result: MiddlewareConfig = {
|
||||||
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 = {
|
|
||||||
root: true,
|
root: true,
|
||||||
parser: '@typescript-eslint/parser',
|
plugins: unique('rules', plugins),
|
||||||
plugins: unique('@typescript-eslint', 'import-x', 'rules', 'unicorn', plugins),
|
|
||||||
env: { node: true, browser: true, es2023: true },
|
env: { node: true, browser: true, es2023: true },
|
||||||
reportUnusedDisableDirectives: true,
|
reportUnusedDisableDirectives: true,
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
project: true,
|
project: true,
|
||||||
...parserOptions,
|
...parserOptions,
|
||||||
},
|
},
|
||||||
extends: unique(
|
ignorePatterns: [],
|
||||||
'eslint:recommended',
|
globals: {},
|
||||||
'prettier',
|
extends: ['eslint:recommended', 'prettier', ...(extend as string[])],
|
||||||
'plugin:@typescript-eslint/recommended-type-checked',
|
settings,
|
||||||
'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,
|
|
||||||
},
|
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{ files: ['repl.ts', 'scripts/**/*.ts'], rules: { 'no-console': off } },
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
...(overrides ?? []),
|
...(overrides ?? []),
|
||||||
],
|
],
|
||||||
rules: {
|
rules: { ...eslintRules, ...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,
|
|
||||||
},
|
|
||||||
...rest,
|
...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;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
import { GraphQLRulesObject } from '@aet/eslint-define-config/src/rules/graphql-eslint';
|
import { GraphQLRulesObject } from '@aet/eslint-define-config/src/rules/graphql-eslint';
|
||||||
|
import type { Middleware } from '../index';
|
||||||
|
|
||||||
// https://the-guild.dev/graphql/eslint/rules
|
// https://the-guild.dev/graphql/eslint/rules
|
||||||
export const graphqlRules: Partial<GraphQLRulesObject> = {};
|
const graphqlRules: Partial<GraphQLRulesObject> = {};
|
||||||
|
|
||||||
|
export const graphql: Middleware = (config, { addRules }) => {
|
||||||
|
config.plugins.push('@graphql-eslint');
|
||||||
|
config.extends.push('plugin:@graphql-eslint/recommended');
|
||||||
|
addRules(graphqlRules);
|
||||||
|
};
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
import { error, off } from '../constants';
|
|
||||||
import { ImportXRulesObject } from '@aet/eslint-define-config/src/rules/import-x';
|
|
||||||
|
|
||||||
export const importRules: Partial<ImportXRulesObject> = {
|
|
||||||
'import-x/export': off,
|
|
||||||
'import-x/no-duplicates': error,
|
|
||||||
'import-x/order': [error, { groups: ['builtin', 'external'] }],
|
|
||||||
};
|
|
@ -1,3 +1,10 @@
|
|||||||
import { JSDocRulesObject } from '@aet/eslint-define-config/src/rules/jsdoc';
|
import { JSDocRulesObject } from '@aet/eslint-define-config/src/rules/jsdoc';
|
||||||
|
import type { Middleware } from '../index';
|
||||||
|
|
||||||
export const jsDocRules: Partial<JSDocRulesObject> = {};
|
const jsdocRules: Partial<JSDocRulesObject> = {};
|
||||||
|
|
||||||
|
export const jsdoc: Middleware = (config, { addRules }) => {
|
||||||
|
config.plugins.push('jsdoc');
|
||||||
|
config.extends.push('plugin:jsdoc/recommended-typescript');
|
||||||
|
addRules(jsdocRules);
|
||||||
|
};
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
import type { LocalRuleOptions } from '..';
|
import type { LocalRuleOptions, Middleware } from '../index';
|
||||||
import { error } from '../constants';
|
import { error } from '../constants';
|
||||||
|
|
||||||
export const localRules: Partial<LocalRuleOptions> = {
|
const localRules: Partial<LocalRuleOptions> = {
|
||||||
'rules/no-import-dot': error,
|
'rules/no-import-dot': error,
|
||||||
'rules/restrict-template-expressions': error,
|
'rules/restrict-template-expressions': error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const local: Middleware = (_, { addRules }) => {
|
||||||
|
addRules(localRules);
|
||||||
|
};
|
||||||
|
9
src/presets/misc.ts
Normal file
9
src/presets/misc.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { Middleware } from '../index';
|
||||||
|
|
||||||
|
export const storybook: Middleware = config => {
|
||||||
|
config.extends.push('plugin:storybook/recommended');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const reactQuery: Middleware = config => {
|
||||||
|
config.extends.push('plugin:@tanstack/eslint-plugin-query/recommended');
|
||||||
|
};
|
@ -1,7 +1,35 @@
|
|||||||
import { error, off } from '../constants';
|
import type { Middleware } from '../index';
|
||||||
|
import { error, off, warn } from '../constants';
|
||||||
import { ReactRulesObject } from '@aet/eslint-define-config/src/rules/react';
|
import { ReactRulesObject } from '@aet/eslint-define-config/src/rules/react';
|
||||||
|
import { ReactRefreshRulesObject } from '@aet/eslint-define-config/src/rules/react-refresh';
|
||||||
|
|
||||||
export const reactRules: Partial<ReactRulesObject> = {
|
const reactRules: Partial<ReactRulesObject> = {
|
||||||
'@eslint-react/no-missing-component-display-name': off,
|
'@eslint-react/no-missing-component-display-name': off,
|
||||||
'@eslint-react/no-children-prop': error,
|
'@eslint-react/no-children-prop': error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const react: Middleware = (config, { addRules }) => {
|
||||||
|
config.plugins.push('@eslint-react/eslint-plugin', 'react-hooks');
|
||||||
|
config.extends.push(
|
||||||
|
'plugin:@eslint-react/recommended-legacy',
|
||||||
|
'plugin:@eslint-react/dom-legacy',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
'plugin:jsx-a11y/recommended',
|
||||||
|
);
|
||||||
|
config.overrides.push({
|
||||||
|
files: ['*.tsx'],
|
||||||
|
rules: {
|
||||||
|
'@eslint-react/no-leaked-conditional-rendering': error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addRules(reactRules);
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshRules: Partial<ReactRefreshRulesObject> = {
|
||||||
|
'react-refresh/only-export-components': [warn, { allowConstantExport: true }],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const reactRefresh: Middleware = (config, { addRules }) => {
|
||||||
|
config.plugins.push('react-refresh');
|
||||||
|
addRules(refreshRules);
|
||||||
|
};
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
|
import type { Middleware } from '../index';
|
||||||
import { off } from '../constants';
|
import { off } from '../constants';
|
||||||
|
import type { TailwindRulesObject } from '@aet/eslint-define-config/src/rules/tailwind';
|
||||||
|
|
||||||
export const tailwindRules = {
|
const tailwindRules: Partial<TailwindRulesObject> = {
|
||||||
'tailwindcss/no-custom-classname': off,
|
'tailwindcss/no-custom-classname': off,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const tailwind: Middleware = (config, { addRules }) => {
|
||||||
|
config.extends.push('plugin:tailwindcss/recommended');
|
||||||
|
addRules(tailwindRules);
|
||||||
|
};
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
import { error, off, warn } from '../constants';
|
import { error, off, warn } from '../constants';
|
||||||
import type { TypeScriptRulesObject } from '@aet/eslint-define-config/src/rules/typescript-eslint';
|
import type { TypeScriptRulesObject } from '@aet/eslint-define-config/src/rules/typescript-eslint';
|
||||||
|
import type { ImportXRulesObject } from '@aet/eslint-define-config/src/rules/import-x';
|
||||||
|
import type { Middleware } from '../index';
|
||||||
|
|
||||||
export const typescriptRules: Partial<TypeScriptRulesObject> = {
|
const importRules: Partial<ImportXRulesObject> = {
|
||||||
|
'import-x/export': off,
|
||||||
|
'import-x/no-duplicates': error,
|
||||||
|
'import-x/order': [error, { groups: ['builtin', 'external'] }],
|
||||||
|
};
|
||||||
|
|
||||||
|
const typescriptRules: Partial<TypeScriptRulesObject> = {
|
||||||
'@typescript-eslint/ban-ts-comment': [
|
'@typescript-eslint/ban-ts-comment': [
|
||||||
error,
|
error,
|
||||||
{
|
{
|
||||||
@ -37,3 +45,39 @@ export const typescriptRules: Partial<TypeScriptRulesObject> = {
|
|||||||
'@typescript-eslint/triple-slash-reference': off,
|
'@typescript-eslint/triple-slash-reference': off,
|
||||||
'@typescript-eslint/unbound-method': off,
|
'@typescript-eslint/unbound-method': off,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const importTypeScript: Middleware = (config, { addRules, addSettings }) => {
|
||||||
|
config.parser = '@typescript-eslint/parser';
|
||||||
|
config.plugins.push('@typescript-eslint', 'import-x');
|
||||||
|
config.extends.push(
|
||||||
|
'plugin:@typescript-eslint/recommended-type-checked',
|
||||||
|
'plugin:import-x/errors',
|
||||||
|
'plugin:import-x/typescript',
|
||||||
|
);
|
||||||
|
addSettings({
|
||||||
|
'import-x/parsers': {
|
||||||
|
'@typescript-eslint/parser': ['.ts', '.tsx', '.mts', '.cts'],
|
||||||
|
},
|
||||||
|
'import-x/resolver': {
|
||||||
|
typescript: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
config.overrides.push(
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
addRules(importRules);
|
||||||
|
addRules(typescriptRules);
|
||||||
|
};
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
|
import type { Middleware } from '../index';
|
||||||
import { error, warn } from '../constants';
|
import { error, warn } from '../constants';
|
||||||
import { UnicornRulesObject } from '@aet/eslint-define-config/src/rules/unicorn';
|
import { UnicornRulesObject } from '@aet/eslint-define-config/src/rules/unicorn';
|
||||||
|
|
||||||
const suggest = (suggest: string) => ({ suggest, fix: false });
|
const suggest = (suggest: string) => ({ suggest, fix: false });
|
||||||
|
|
||||||
// https://github.com/sindresorhus/eslint-plugin-unicorn/tree/28e7498ad06679bb92343db53bb40a7b5ba2990a
|
// https://github.com/sindresorhus/eslint-plugin-unicorn/tree/28e7498ad06679bb92343db53bb40a7b5ba2990a
|
||||||
export const unicornRules: Partial<UnicornRulesObject> = {
|
const unicornRules: Partial<UnicornRulesObject> = {
|
||||||
'unicorn/better-regex': error,
|
'unicorn/better-regex': error,
|
||||||
'unicorn/consistent-function-scoping': warn,
|
'unicorn/consistent-function-scoping': warn,
|
||||||
'unicorn/escape-case': error,
|
'unicorn/escape-case': error,
|
||||||
@ -69,3 +70,8 @@ export const unicornRules: Partial<UnicornRulesObject> = {
|
|||||||
],
|
],
|
||||||
'unicorn/template-indent': warn,
|
'unicorn/template-indent': warn,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const unicorn: Middleware = (config, { addRules }) => {
|
||||||
|
config.plugins.push('unicorn');
|
||||||
|
addRules(unicornRules);
|
||||||
|
};
|
||||||
|
Reference in New Issue
Block a user