@hyperse/eslint-config-hyperse
Version:
🛠These are settings for TypeScript / ESLint / Prettier in a project
317 lines (311 loc) • 9.29 kB
JavaScript
import { defineFlatConfig } from 'eslint-define-config';
import appRoot from 'app-root-path';
import simpleImportSort from 'eslint-plugin-simple-import-sort';
import { getTsconfig } from 'get-tsconfig';
import pluginJsonc from 'eslint-plugin-jsonc';
import * as pluginMdx from 'eslint-plugin-mdx';
import pluginNext from '@next/eslint-plugin-next';
import eslintPluginPrettier from 'eslint-plugin-prettier/recommended';
import pluginReact from 'eslint-plugin-react';
import pluginReactHooks from 'eslint-plugin-react-hooks';
import globals from 'globals';
import regexpPlugin from 'eslint-plugin-regexp';
import sonarjs from 'eslint-plugin-sonarjs';
import tseslint from 'typescript-eslint';
import eslint from '@eslint/js';
import pluginVitest from '@vitest/eslint-plugin';
// src/main/reactjs.ts
function extractPaths(paths) {
return Object.keys(paths).map((key) => {
return key.split("/")[0];
});
}
var tsConfig = getTsconfig(appRoot.path, "tsconfig.json");
var jsConfig = getTsconfig(appRoot.path, "jsconfig.json");
var pathsNames = [];
if (tsConfig && tsConfig.config.compilerOptions?.paths) {
pathsNames = extractPaths(tsConfig.config.compilerOptions.paths);
} else if (jsConfig && jsConfig.config.compilerOptions?.paths) {
pathsNames = extractPaths(jsConfig.config.compilerOptions.paths);
}
var imports = defineFlatConfig([
{
plugins: {
"simple-import-sort": simpleImportSort
},
rules: {
"simple-import-sort/exports": "error",
"simple-import-sort/imports": [
"error",
{
groups: [
[
// Anything that starts with react
// e.g: import { useState } from 'react'
// e.g: import { useFela } from 'react-fela'
"^react",
// Anything that starts with next
// e.g: import { useRouter } from 'next/router'
"^next",
// Anything that starts with a letter
// e.g: import Downshift from 'downshift'
"^[a-z]",
// Anything that starts with an alias (see jsconfig.json)
// e.g: import ListDropdown from '@shared/components/ListDropdown'
`^(${pathsNames.join("|")})(/.*|$)`,
// Anything that starts with @
// e.g: import { yupResolver } from '@hookform/resolvers/yup'
"^@",
// Anything that starts with a dot
// e.g: import { matchIsDate } from './utils/date
"^\\.",
// Side effect imports from lib
// e.g: import 'react-toastify/dist/ReactToastify.css'
"^\\u0000",
// Side effect import that starts with a dot
// e.g: import './setup-config'
"^\\u0000\\."
]
]
}
]
}
}
]);
var jsonc = defineFlatConfig([
...pluginJsonc.configs["flat/recommended-with-jsonc"],
{
rules: {
// override/add rules settings here, such as:
// 'jsonc/rule-name': 'error'
}
}
]);
var mdx = defineFlatConfig([
{
...pluginMdx.flat
}
]);
defineFlatConfig([
{
plugins: {
"@next/next": pluginNext
},
rules: {
...pluginNext.configs.recommended.rules,
...pluginNext.configs["core-web-vitals"].rules
}
},
{
ignores: [".next/*"]
}
]);
// src/getPrettierConfig.ts
var prettierBaseConfig = {
// add semicolons at the end of statements
semi: true,
// use single quotes instead of double quotes
singleQuote: true,
// add trailing commas where valid in ES5 (objects, arrays, etc.)
trailingComma: "es5"
// keep it as default value for windows, mac endOfLine(lf).
};
var getPrettierConfig = (config = {}) => {
return {
...prettierBaseConfig,
...config,
// highlight priority on .prettierrc
plugins: ["prettier-plugin-tailwindcss"]
};
};
var { ...prettierConfig } = getPrettierConfig();
var prettier = defineFlatConfig([
{
...eslintPluginPrettier,
rules: {
...eslintPluginPrettier.rules,
"prettier/prettier": ["error", prettierConfig]
}
}
]);
var reactPatterns = {
files: ["**/*.{jsx,tsx}"]
};
var react = defineFlatConfig([
{
files: reactPatterns.files,
...pluginReact.configs.flat.recommended,
languageOptions: {
...pluginReact.configs.flat.recommended.languageOptions,
globals: {
...globals.serviceworker,
...globals.browser
}
},
rules: {
// The full available rules before can be found here
// https://github.com/hyperse-io/eslint-config-hyperse/blob/1e23efbfb64f4e5a8b0c6387d187b7f6341f1e61/src/rules/react.ts
...pluginReact.configs.flat.recommended.rules,
"react/react-in-jsx-scope": "off",
"react-hooks/exhaustive-deps": "off",
"react/prop-types": "off"
},
settings: {
react: {
version: "detect"
// Automatically detect React version
}
}
},
{
files: reactPatterns.files,
...pluginReactHooks.configs["recommended-latest"]
}
]);
var regexpPatterns = {
files: ["**/*.{js,jsx,jsx,tsx,mts,cts,mjs,cjs}"]
};
var regexp = defineFlatConfig([
{
files: regexpPatterns.files,
plugins: {
regexp: regexpPlugin
},
rules: {
...regexpPlugin.configs.recommended.rules,
"regexp/prefer-result-array-groups": "off"
}
}
]);
var sonarPatterns = {
files: ["**/*.{js,jsx,ts,tsx,mts,cts,mjs,cjs}"],
excludedFiles: [
"**/?(*.)+(test).{js,jsx,ts,tsx,mts,cts,mjs,cjs}",
"**/?(*.)+(spec).{js,jsx,ts,tsx,mts,cts,mjs,cjs}",
"*.stories.{js,ts,jsx,tsx,mts,cts,mjs,cjs}"
]
};
defineFlatConfig([
{
files: sonarPatterns.files,
ignores: sonarPatterns.excludedFiles,
plugins: {
sonarjs
},
rules: {
...sonarjs.configs.recommended.rules,
"sonarjs/cognitive-complexity": ["error", 20],
"sonarjs/max-switch-cases": ["error", 20],
"sonarjs/no-all-duplicated-branches": "error",
"sonarjs/no-element-overwrite": "error",
"sonarjs/no-identical-functions": "error",
"sonarjs/no-identical-expressions": "error",
"sonarjs/no-hook-setter-in-body": "off",
"sonarjs/public-static-readonly": "off",
"sonarjs/no-nested-conditional": "off",
"sonarjs/fixme-tag": "warn",
"sonarjs/todo-tag": "warn",
// NOTE: performance issue for this rule
// https://community.sonarsource.com/t/eslint-plugin-sonarjs-performance-issues-on-large-codebase/138392
"sonarjs/no-commented-code": "off",
// NOTE: This rule has performance issue and now use `@typescript-eslint/no-deprecated` instead
"sonarjs/deprecation": "off"
}
}
]);
var typescript = defineFlatConfig(
tseslint.config(
{
languageOptions: {
globals: {
...globals.node
}
}
},
eslint.configs.recommended,
...tseslint.configs.recommended
// ...tseslint.configs.recommendedTypeChecked,
// ...tseslint.configs.stylisticTypeChecked
)
);
var vitestPatterns = {
files: ["**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"]
};
var vitest = defineFlatConfig([
{
files: vitestPatterns.files,
plugins: {
vitest: pluginVitest
},
rules: {
// you can also use vitest.configs.all.rules to enable all rules
...pluginVitest.configs.recommended.rules,
// you can also modify rules' behavior using option like this
"vitest/max-nested-describe": ["error", { max: 3 }],
"vitest/no-disabled-tests": 2,
"vitest/valid-title": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-object-literal-type-assertion": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-comment": "off"
},
settings: {
vitest: {
typecheck: true
}
},
languageOptions: {
globals: {
...pluginVitest.environments.env.globals
}
}
}
]);
var overrides = defineFlatConfig([
{
...tseslint.configs.base,
languageOptions: {
// https://typescript-eslint.io/users/configs/#stylistic-type-checked
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
// https://github.com/typescript-eslint/typescript-eslint/issues/10200
// Support `nestjs` decorator metadata, constructor DI class, we can not import type for `nestjs`
emitDecoratorMetadata: true
}
},
files: ["**/*.ts", "**/*.tsx"],
rules: {
"@typescript-eslint/no-unused-vars": [
"warn",
{
args: "all",
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_"
}
],
"@typescript-eslint/consistent-type-imports": [
"error",
{ disallowTypeAnnotations: false }
],
// Use this rule instead of `sonarjs/deprecation`
"@typescript-eslint/no-deprecated": "warn"
}
}
]);
// src/main/base.ts
var base = defineFlatConfig([
...typescript,
...vitest,
...imports,
...prettier,
...regexp,
...jsonc,
...mdx,
...overrides
]);
// src/main/reactjs.ts
var reactjs = defineFlatConfig([...base, ...react]);
export { reactjs };