This commit is contained in:
Alex 2025-01-25 19:44:09 -05:00
parent 8824c2166d
commit c2d582dea0
13 changed files with 926 additions and 1007 deletions

View File

@ -7,6 +7,16 @@ export type Middleware =
| (() => Promise<MiddlewareResult>)
| (() => Promise<{ default: MiddlewareResult }>);
export type Environment =
| 'react'
| 'reactRefresh'
| 'tailwind'
| 'storybook'
| 'reactQuery'
| 'testingLibrary'
| 'jsdoc'
| 'vitest';
export interface NormalizedExtendConfigOptions {
auto?: boolean;
middlewares?: Middleware[];
@ -15,6 +25,9 @@ export interface NormalizedExtendConfigOptions {
* Use `.gitignore` file to exclude files from ESLint.
*/
gitignore?: boolean;
env?: {
[key in Environment]?: boolean;
};
}
export type ExtendConfigOptions =

30
dist/package.json vendored
View File

@ -1,6 +1,6 @@
{
"name": "@aet/eslint-rules",
"version": "2.0.26",
"version": "2.0.29",
"license": "UNLICENSED",
"type": "module",
"bin": {
@ -23,18 +23,18 @@
"@tanstack/eslint-plugin-query": "^5.62.1"
},
"dependencies": {
"@aet/eslint-define-config": "^0.1.3",
"@antfu/install-pkg": "^0.5.0",
"@aet/eslint-define-config": "^0.1.5",
"@antfu/install-pkg": "^1.0.0",
"@eslint-community/eslint-utils": "^4.4.1",
"@eslint-react/eslint-plugin": "1.22.1",
"@eslint/js": "^9.17.0",
"@eslint-react/eslint-plugin": "1.24.1",
"@eslint/js": "^9.19.0",
"@nolyfill/is-core-module": "^1.0.39",
"@stylistic/eslint-plugin": "^2.12.1",
"@stylistic/eslint-plugin": "^3.0.0",
"@types/eslint": "^9.6.1",
"@typescript-eslint/eslint-plugin": "^8.18.2",
"@typescript-eslint/parser": "^8.18.2",
"@typescript-eslint/type-utils": "^8.18.2",
"@typescript-eslint/utils": "^8.18.2",
"@typescript-eslint/eslint-plugin": "^8.21.0",
"@typescript-eslint/parser": "^8.21.0",
"@typescript-eslint/type-utils": "^8.21.0",
"@typescript-eslint/utils": "^8.21.0",
"aria-query": "^5.3.2",
"axe-core": "^4.10.2",
"axobject-query": "4.1.0",
@ -43,7 +43,7 @@
"doctrine": "^3.0.0",
"emoji-regex": "^10.4.0",
"enhanced-resolve": "^5.18.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-prettier": "^10.0.1",
"eslint-import-resolver-node": "^0.3.9",
"eslint-import-resolver-typescript": "^3.7.0",
"eslint-module-utils": "^2.12.0",
@ -52,17 +52,17 @@
"esprima": "^4.0.1",
"esquery": "^1.6.0",
"estraverse": "^5.3.0",
"fast-glob": "^3.3.2",
"get-tsconfig": "^4.8.1",
"fast-glob": "^3.3.3",
"get-tsconfig": "^4.10.0",
"globals": "^15.14.0",
"ignore": "^7.0.0",
"ignore": "^7.0.3",
"is-bun-module": "^1.3.0",
"is-glob": "^4.0.3",
"language-tags": "^2.0.1",
"lodash-es": "^4.17.21",
"minimatch": "^10.0.1",
"semver": "^7.6.3",
"typescript-eslint": "^8.18.2"
"typescript-eslint": "^8.21.0"
},
"pnpm": {
"overrides": {

View File

@ -11,18 +11,18 @@
},
"private": true,
"dependencies": {
"@aet/eslint-define-config": "^0.1.3",
"@antfu/install-pkg": "^0.5.0",
"@aet/eslint-define-config": "^0.1.5",
"@antfu/install-pkg": "^1.0.0",
"@eslint-community/eslint-utils": "^4.4.1",
"@eslint-react/eslint-plugin": "1.22.1",
"@eslint/js": "^9.17.0",
"@eslint-react/eslint-plugin": "1.24.1",
"@eslint/js": "^9.19.0",
"@nolyfill/is-core-module": "^1.0.39",
"@stylistic/eslint-plugin": "^2.12.1",
"@stylistic/eslint-plugin": "^3.0.0",
"@types/eslint": "^9.6.1",
"@typescript-eslint/eslint-plugin": "^8.18.2",
"@typescript-eslint/parser": "^8.18.2",
"@typescript-eslint/type-utils": "^8.18.2",
"@typescript-eslint/utils": "^8.18.2",
"@typescript-eslint/eslint-plugin": "^8.21.0",
"@typescript-eslint/parser": "^8.21.0",
"@typescript-eslint/type-utils": "^8.21.0",
"@typescript-eslint/utils": "^8.21.0",
"aria-query": "^5.3.2",
"axe-core": "^4.10.2",
"axobject-query": "4.1.0",
@ -31,7 +31,7 @@
"doctrine": "^3.0.0",
"emoji-regex": "^10.4.0",
"enhanced-resolve": "^5.18.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-prettier": "^10.0.1",
"eslint-import-resolver-node": "^0.3.9",
"eslint-import-resolver-typescript": "^3.7.0",
"eslint-module-utils": "^2.12.0",
@ -40,25 +40,25 @@
"esprima": "^4.0.1",
"esquery": "^1.6.0",
"estraverse": "^5.3.0",
"fast-glob": "^3.3.2",
"get-tsconfig": "^4.8.1",
"fast-glob": "^3.3.3",
"get-tsconfig": "^4.10.0",
"globals": "^15.14.0",
"ignore": "^7.0.0",
"ignore": "^7.0.3",
"is-bun-module": "^1.3.0",
"is-glob": "^4.0.3",
"language-tags": "^2.0.1",
"lodash-es": "^4.17.21",
"minimatch": "^10.0.1",
"semver": "^7.6.3",
"typescript-eslint": "^8.18.2"
"typescript-eslint": "^8.21.0"
},
"devDependencies": {
"@babel/core": "^7.26.0",
"@babel/plugin-transform-flow-strip-types": "^7.25.9",
"@babel/preset-env": "^7.26.0",
"@babel/core": "^7.26.7",
"@babel/plugin-transform-flow-strip-types": "^7.26.5",
"@babel/preset-env": "^7.26.7",
"@graphql-eslint/eslint-plugin": "^4.3.0",
"@swc-node/register": "^1.10.9",
"@tanstack/eslint-plugin-query": "^5.62.9",
"@tanstack/eslint-plugin-query": "^5.64.2",
"@types/babel-plugin-macros": "^3.1.3",
"@types/babel__core": "^7.20.5",
"@types/eslint-config-prettier": "^6.11.3",
@ -69,19 +69,19 @@
"@types/estree": "^1.0.6",
"@types/estree-jsx": "^1.0.5",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.10.2",
"@types/node": "^22.10.10",
"@types/react-refresh": "^0.14.6",
"@typescript-eslint/types": "^8.18.2",
"@typescript-eslint/typescript-estree": "^8.18.2",
"@vitest/eslint-plugin": "^1.1.21",
"@typescript-eslint/types": "^8.21.0",
"@typescript-eslint/typescript-estree": "^8.21.0",
"@vitest/eslint-plugin": "^1.1.25",
"babel-plugin-macros": "^3.1.0",
"dts-bundle-generator": "9.5.1",
"esbuild": "0.24.2",
"esbuild-plugin-alias": "^0.2.1",
"eslint": "^9.17.0",
"eslint-plugin-jsdoc": "^50.6.1",
"eslint-plugin-react-refresh": "^0.4.16",
"eslint-plugin-storybook": "^0.11.1",
"eslint": "^9.19.0",
"eslint-plugin-jsdoc": "^50.6.3",
"eslint-plugin-react-refresh": "^0.4.18",
"eslint-plugin-storybook": "^0.11.2",
"eslint-plugin-testing-library": "^7.1.1",
"find-cache-dir": "^5.0.0",
"graphql": "^16.10.0",
@ -92,8 +92,8 @@
"prettier": "^3.4.2",
"prop-types": "^15.8.1",
"terser": "^5.37.0",
"type-fest": "^4.31.0",
"typescript": "^5.7.2"
"type-fest": "^4.33.0",
"typescript": "^5.7.3"
},
"prettier": {
"arrowParens": "avoid",

1767
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,6 @@ pull() {
echo
}
pull import-js eslint-import-resolver-typescript
pull jsx-eslint eslint-plugin-jsx-a11y
pull eslint-community eslint-plugin-n
pull jsx-eslint jsx-ast-utils

View File

@ -1,4 +1,4 @@
#!/usr/bin/env node --experimental-strip-types
#!/usr/bin/env node
import fs from 'node:fs';
const up = JSON.parse(

View File

@ -5,12 +5,6 @@
"committer": "Jordan Harband",
"subject": "[meta] add `repository.directory` field"
},
"eslint-import-resolver-typescript": {
"hash": "ceadb103672e12af2ce9ac30b3ab4965ef581f2f",
"date": "2024-12-16T22:03:20+08:00",
"committer": "GitHub",
"subject": "chore(#331): drop `is-glob` (#332)"
},
"eslint-plugin-jsx-a11y": {
"hash": "91e39b45ade789c86ae14df869a86b0ea468ed95",
"date": "2024-12-25T15:11:08-06:00",

13
src/config.d.ts vendored
View File

@ -7,6 +7,16 @@ export type Middleware =
| (() => Promise<MiddlewareResult>)
| (() => Promise<{ default: MiddlewareResult }>);
export type Environment =
| 'react'
| 'reactRefresh'
| 'tailwind'
| 'storybook'
| 'reactQuery'
| 'testingLibrary'
| 'jsdoc'
| 'vitest';
export interface NormalizedExtendConfigOptions {
auto?: boolean;
middlewares?: Middleware[];
@ -15,6 +25,9 @@ export interface NormalizedExtendConfigOptions {
* Use `.gitignore` file to exclude files from ESLint.
*/
gitignore?: boolean;
env?: {
[key in Environment]?: boolean;
};
}
export type ExtendConfigOptions =

View File

@ -1,6 +1,7 @@
import fs from 'node:fs';
import path from 'node:path';
import type { Environment, NormalizedExtendConfigOptions } from './config';
import type { Middleware } from './middleware';
import { reactQuery, storybook, vitest } from './presets/misc';
import { react, reactRefresh } from './presets/react';
@ -14,7 +15,7 @@ type RemoveType<T extends string> = T extends `@types/${infer U}__${infer V}`
? U
: T;
const middlewares = {
export const middlewares = {
react,
reactRefresh,
tailwind: () => import('./presets/tailwind'),
@ -24,7 +25,7 @@ const middlewares = {
jsdoc: () => import('./presets/jsdoc'),
vitest,
} satisfies {
[key: string]: Middleware;
[key in Environment]: Middleware;
};
export const envs: {
@ -97,3 +98,11 @@ export function* checkEnv(): Generator<Middleware> {
}
}
}
export function* fromEnvironments(envs: NormalizedExtendConfigOptions['env']) {
for (const [env, enabled] of Object.entries(envs ?? {}) as [Environment, boolean][]) {
if (enabled) {
yield middlewares[env];
}
}
}

View File

@ -9,8 +9,8 @@ import tseslint from 'typescript-eslint';
import type { ExtendConfigOptions, NormalizedExtendConfigOptions } from './config';
import { off } from './constants';
import { checkEnv } from './environment';
import { Middleware } from './middleware';
import { checkEnv, fromEnvironments } from './environment';
import type { Middleware } from './middleware';
import { eslintRules } from './presets/eslint';
import stylistic from './presets/stylistic';
import { importRules, typescriptRules } from './presets/typescript';
@ -32,6 +32,7 @@ function normalizeExtendConfig(
middlewares = [],
configs = [],
gitignore = true,
env,
} = options as NormalizedExtendConfigOptions;
return {
@ -39,6 +40,7 @@ function normalizeExtendConfig(
middlewares,
configs,
gitignore,
env,
};
}
@ -50,14 +52,15 @@ export async function extendConfig(
middlewares: addMiddlewares = [],
configs,
gitignore,
env,
} = normalizeExtendConfig(options);
const middlewares: Middleware[] = uniq([
() => import('./presets/custom'),
...(auto ? checkEnv() : []),
...fromEnvironments(env),
...addMiddlewares,
]);
const result: FlatESLintConfig[] = [
{
name: 'eslint-rules/eslint',

View File

@ -16,7 +16,7 @@ export default defineConfig([
settings: {
tailwindcss: {
callees: ['classnames', 'clsx', 'tw', 'twx'],
classRegex: '^(css|class(Name)?)$',
classRegex: /^(css|class(Name)?)$/.source,
},
},
},

View File

@ -40,6 +40,14 @@ export const typescriptRules: Partial<TypeScriptRulesObject> = {
'@typescript-eslint/no-empty-object-type': off,
'@typescript-eslint/no-empty-interface': [error, { allowSingleExtends: true }],
'@typescript-eslint/no-explicit-any': off,
'@typescript-eslint/no-floating-promises': [
'warn',
{
allowForKnownSafeCalls: [
{ from: 'package', name: ['it', 'describe', 'test'], package: 'node:test' },
],
},
],
'@typescript-eslint/no-misused-promises': [error, { checksVoidReturn: false }],
'@typescript-eslint/no-namespace': off,
'@typescript-eslint/no-unnecessary-type-assertion': error,

View File

@ -7,10 +7,12 @@ import { defineConfig } from '../types';
const suggest = (suggest: string) => ({ suggest, fix: false });
// https://github.com/sindresorhus/eslint-plugin-unicorn/tree/28e7498ad06679bb92343db53bb40a7b5ba2990a
// https://github.com/sindresorhus/eslint-plugin-unicorn/tree/1774135a5ddbded2c89f82952e37a3e3bb01cdfa
const unicornRules: Partial<UnicornRulesObject> = {
'unicorn/better-regex': error,
'unicorn/consistent-destructuring': warn,
'unicorn/consistent-empty-array-spread': error,
'unicorn/consistent-existence-index-check': error,
'unicorn/consistent-function-scoping': warn,
'unicorn/escape-case': error,
'unicorn/no-array-for-each': warn,
@ -22,6 +24,7 @@ const unicornRules: Partial<UnicornRulesObject> = {
'unicorn/no-instanceof-array': error,
'unicorn/no-invalid-fetch-options': error,
'unicorn/no-invalid-remove-event-listener': error,
'unicorn/no-length-as-slice-end': error,
'unicorn/no-lonely-if': warn,
'unicorn/no-negation-in-equality-check': error,
'unicorn/no-new-buffer': error,
@ -38,6 +41,7 @@ const unicornRules: Partial<UnicornRulesObject> = {
'unicorn/no-useless-undefined': error,
'unicorn/no-zero-fractions': error,
'unicorn/number-literal-case': error,
'unicorn/prefer-array-index-of': error,
'unicorn/prefer-array-find': error,
'unicorn/prefer-array-flat': error,
'unicorn/prefer-array-flat-map': error,
@ -54,6 +58,7 @@ const unicornRules: Partial<UnicornRulesObject> = {
'unicorn/prefer-json-parse-buffer': warn,
'unicorn/prefer-keyboard-event-key': warn,
'unicorn/prefer-logical-operator-over-ternary': warn,
'unicorn/prefer-math-min-max': error,
'unicorn/prefer-math-trunc': warn,
'unicorn/prefer-modern-dom-apis': error,
'unicorn/prefer-modern-math-apis': error,
@ -66,14 +71,16 @@ const unicornRules: Partial<UnicornRulesObject> = {
'unicorn/prefer-regexp-test': error,
'unicorn/prefer-set-has': warn,
'unicorn/prefer-set-size': error,
'unicorn/prefer-string-raw': error,
'unicorn/prefer-string-raw': warn,
'unicorn/prefer-string-slice': error,
'unicorn/prefer-string-starts-ends-with': warn,
'unicorn/prefer-string-trim-start-end': error,
'unicorn/prefer-switch': warn,
'unicorn/prefer-ternary': warn,
'unicorn/prefer-type-error': warn,
'unicorn/relative-url-style': warn,
'unicorn/require-number-to-fixed-digits-argument': error,
'unicorn/require-post-message-target-origin': warn,
'unicorn/string-content': [
warn,
{