Files
frontend/eslint.config.mjs
T
ksv741 851457e03c
Frontend security / security (push) Successful in 9s
Frontend verify / verify (push) Failing after 17m37s
Conventional commits / commits (pull_request) Successful in 26s
Frontend security / security (pull_request) Successful in 9s
Frontend verify / verify (pull_request) Failing after 22m42s
chore: add typed ESLint checks #18
Refs WealthLedger/main#18. Keep Biome; add no Prettier dependencies.
2026-09-28 05:52:29 +03:00

132 lines
4.3 KiB
JavaScript

import js from "@eslint/js";
import react from "@eslint-react/eslint-plugin";
import query from "@tanstack/eslint-plugin-query";
import vitest from "@vitest/eslint-plugin";
import { defineConfig, globalIgnores } from "eslint/config";
import { importX } from "eslint-plugin-import-x";
import hooks from "eslint-plugin-react-hooks";
import refresh from "eslint-plugin-react-refresh";
import storybook from "eslint-plugin-storybook";
import testingLibrary from "eslint-plugin-testing-library";
import unicorn from "eslint-plugin-unicorn";
import globals from "globals";
import tseslint from "typescript-eslint";
export default defineConfig(
globalIgnores([
"**/dist/**",
"dist-ssr/**",
"storybook-static/**",
"coverage/**",
".vitest/**",
".scannerwork/**",
"src/shared/api/generated/**",
"src/shared/api/spec/**",
]),
{
files: ["**/*.{js,mjs,cjs,ts,tsx}"],
extends: [js.configs.recommended],
linterOptions: { reportUnusedDisableDirectives: "error" },
},
{
files: ["**/*.{js,mjs,cjs}", "**/*.config.ts", ".storybook/main.ts"],
languageOptions: { globals: globals.node },
},
{
files: ["**/*.{ts,tsx}"],
extends: [tseslint.configs.recommendedTypeChecked],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
"@typescript-eslint/switch-exhaustiveness-check": "error",
// React ignores handler return values; their bodies still check floating promises.
"@typescript-eslint/no-misused-promises": [
"error",
{ checksVoidReturn: { attributes: false } },
],
},
},
{
files: [
"src/**/*.{ts,tsx}",
"packages/*/src/**/*.{ts,tsx}",
".storybook/preview.tsx",
],
extends: [
react.configs["recommended-type-checked"],
react.configs["disable-naming-convention"],
hooks.configs.flat.recommended,
query.configs["flat/recommended"],
],
languageOptions: { globals: globals.browser },
plugins: { "import-x": importX, unicorn },
rules: {
// The official hooks plugin owns Compiler and hook diagnostics.
"@eslint-react/error-boundaries": "off",
"@eslint-react/exhaustive-deps": "off",
"@eslint-react/purity": "off",
"@eslint-react/rules-of-hooks": "off",
"@eslint-react/set-state-in-effect": "off",
"@eslint-react/set-state-in-render": "off",
"@eslint-react/static-components": "off",
"@eslint-react/unsupported-syntax": "off",
"@eslint-react/use-memo": "off",
// useContext remains supported; a lint rollout does not require an API migration.
"@eslint-react/no-use-context": "off",
"import-x/no-default-export": "error",
"import-x/exports-last": "error",
// Biome owns formatting, import sorting and magic numbers during coexistence.
"unicorn/no-array-fill-with-reference-type": "error",
"unicorn/no-await-in-promise-methods": "error",
"unicorn/no-single-promise-in-promise-methods": "error",
"unicorn/prefer-array-some": "error",
"unicorn/prefer-includes": "error",
},
},
{
files: ["src/**/*.tsx", "packages/*/src/**/*.tsx"],
ignores: ["**/*.test.tsx", "**/*.stories.tsx", "src/test/**"],
extends: [refresh.configs.vite],
},
{
files: ["**/*.test.{ts,tsx}"],
extends: [vitest.configs.recommended],
rules: {
"vitest/no-focused-tests": "error",
"vitest/valid-expect": ["error", { maxArgs: 2 }],
// it.each cases select different expected outcomes and recovery setup steps.
"vitest/no-conditional-expect": "off",
// Async test doubles preserve the public Promise contract without artificial awaits.
"@typescript-eslint/require-await": "off",
},
},
{
files: ["**/*.test.tsx"],
plugins: { "testing-library": testingLibrary },
// Start with async correctness. DOM structure/geometry tests need direct node access.
rules: {
"testing-library/await-async-events": "error",
"testing-library/await-async-queries": "error",
"testing-library/await-async-utils": "error",
"testing-library/no-await-sync-events": "error",
"testing-library/no-await-sync-queries": "error",
"testing-library/no-promise-in-fire-event": "error",
"testing-library/no-wait-for-side-effects": "error",
"testing-library/no-wait-for-snapshot": "error",
"testing-library/prefer-find-by": "error",
},
},
storybook.configs["flat/recommended"],
{
files: ["**/*.stories.tsx", ".storybook/preview.tsx"],
rules: {
"import-x/no-default-export": "off",
"import-x/exports-last": "off",
},
},
);