import type { FlatESLintConfig } from '@aet/eslint-define-config'; import * as tsParser from '@typescript-eslint/parser'; import importPlugin from 'eslint-plugin-import-x'; import { uniq } from 'lodash-es'; import tseslint from 'typescript-eslint'; import { off } from './constants'; import { checkEnv } from './environment'; import { Middleware } from './middleware'; import { eslintRules } from './presets/eslint'; import stylistic from './presets/stylistic'; import { importRules, typescriptRules } from './presets/typescript'; import unicorn from './presets/unicorn'; export { error, warn, off } from './constants'; export async function extendConfig({ auto = true, middlewares: addMiddlewares = [], configs = [], }: { auto?: boolean; middlewares?: Middleware[]; configs: FlatESLintConfig[]; }): Promise { const middlewares: Middleware[] = uniq([ () => import('./presets/custom'), ...(auto ? checkEnv() : []), ...addMiddlewares, ]); const result: FlatESLintConfig[] = [ { name: 'eslint-rules/eslint', rules: eslintRules, }, ...tseslint.configs.recommendedTypeChecked, importPlugin.flatConfigs.recommended, importPlugin.flatConfigs.react, importPlugin.flatConfigs.typescript, ...unicorn, stylistic, { name: 'eslint-rules: TypeScript and import-x', files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'], languageOptions: { parserOptions: { parser: tsParser, projectService: true, ecmaVersion: 'latest', tsconfigRootDir: import.meta.dirname, sourceType: 'module', }, }, settings: { 'import-x/parsers': { '@typescript-eslint/parser': ['.ts', '.tsx', '.mts', '.cts'], }, 'import-x/resolver': { typescript: true, node: true, }, 'import-x/core-modules': ['node:sqlite'], }, ignores: ['eslint.config.cjs'], rules: { ...importRules, ...typescriptRules, }, }, { name: 'eslint-rules: Disable type checking', files: ['*.js', '*.mjs', '*.cjs', '*.jsx'], ...tseslint.configs.disableTypeChecked, rules: { 'import-x/no-commonjs': off, 'import-x/unambiguous': off, '@typescript-eslint/no-require-imports': off, 'typed-custom/restrict-template-expressions': off, ...tseslint.configs.disableTypeChecked.rules, }, }, { name: 'eslint-rules: .d.ts files', files: ['*.d.ts'], rules: { '@typescript-eslint/consistent-type-imports': off, 'import-x/unambiguous': off, }, }, ] as FlatESLintConfig[]; for (const middleware of middlewares) { let fn = await middleware(); if ('default' in fn) { fn = fn.default; } if (Array.isArray(fn)) { result.push(...(fn as FlatESLintConfig[]).flat(Infinity)); } else { result.push(fn as unknown as FlatESLintConfig); } } if (configs) { result.push(...configs); } return result; }