diff --git a/.golangci.yml b/.golangci.yml index 5b1268f..dd3226d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,7 +5,9 @@ linters-settings: sections: - standard - default - - prefix(go.yrps.dev) + - prefix(go.c3c.cz) + forbidigo: + analyze-types: true gocritic: enabled-tags: - diagnostic @@ -26,8 +28,16 @@ linters-settings: require-explanation: true require-specific: true sloglint: - no-global: "all" - context: "scope" + attr-only: true + context: scope + forbidden-keys: + - time + - level + - msg + - source + key-naming-case: snake + no-global: all + static-msg: true stylecheck: checks: - all @@ -40,12 +50,15 @@ linters: enable: - bidichk - bodyclose + - canonicalheader - copyloopvar - errcheck - errorlint - exhaustive + - forbidigo - gci - gocheckcompilerdirectives + - gochecksumtype - goconst - gocritic - gofumpt @@ -53,20 +66,30 @@ linters: - gosimple - govet - ineffassign + - makezero + - mirror - misspell + - nakedret + - nilnil - noctx - nolintlint + - nosprintfhostport + - perfsprint - prealloc - predeclared - protogetter - sloglint + - spancheck - staticcheck - stylecheck - unconvert + - unconvert - unparam - unused - whitespace - usestdlibvars + - wastedassign + - whitespace - wsl issues: diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..cdd981e --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,152 @@ +import jseslint from "@eslint/js"; +import eslintPluginImportX from "eslint-plugin-import-x"; +import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; +import eslintPluginReact from "eslint-plugin-react"; +import eslintPluginReactHooks from "eslint-plugin-react-hooks"; +import eslintPluginReactRefresh from "eslint-plugin-react-refresh"; +import eslintPluginFormatjs from "eslint-plugin-formatjs"; +import tseslint from "typescript-eslint"; + +// This config is provided through nix environment. +// Config is meant to be injected through devshell env variable and "cp" command in .envrc to copy it in the proper path + +// Install dependencies: npm i -D @eslint/js@9 eslint-plugin-import-x@4 eslint-plugin-prettier@5 eslint-plugin-react@7 eslint-plugin-react-hooks@5 eslint-plugin-react-refresh@0.4 eslint-plugin-formatjs@5 typescript-eslint@8 + +export default tseslint.config( + { + ignores: [ + "build/", + "dist/", + "tsconfig.json", + "tsconfig.*.json", + "eslint.config.mjs", + ], + }, + jseslint.configs.recommended, + ...tseslint.configs.recommendedTypeChecked, + eslintPluginImportX.flatConfigs.recommended, + eslintPluginImportX.flatConfigs.typescript, + eslintPluginReact.configs.flat.recommended, + eslintPluginPrettierRecommended, + { + languageOptions: { + parserOptions: { + tsconfigRootDir: import.meta.dirname, + project: "./tsconfig.json", + }, + }, + settings: { + react: { + version: "detect", + }, + "import-x/resolver": { + typescript: true, + node: true, + }, + }, + plugins: { + "react-hooks": eslintPluginReactHooks, + "react-refresh": eslintPluginReactRefresh, + formatjs: eslintPluginFormatjs, + }, + rules: { + curly: ["error"], + "no-console": ["warn"], + "no-constant-condition": [ + "error", + { + checkLoops: "allExceptWhileTrue", + }, + ], + + // Typescript + // Some non typescript rules must be disabled as they can report incorrect errors + "default-param-last": "off", + "@typescript-eslint/default-param-last": "error", + "dot-notation": "off", + "@typescript-eslint/dot-notation": [ + "error", + { + allowKeywords: true, + }, + ], + "@typescript-eslint/naming-convention": [ + "error", + { + selector: ["function", "import"], + format: ["camelCase", "PascalCase"], + }, + { + selector: ["variable"], + format: ["camelCase", "PascalCase", "UPPER_CASE"], + }, + { + selector: ["enum", "typeLike"], + format: ["PascalCase"], + }, + ], + "@typescript-eslint/no-unused-vars": [ + "warn", + { + args: "after-used", + caughtErrors: "all", + caughtErrorsIgnorePattern: "^_$", + }, + ], + "no-use-before-define": "off", + "@typescript-eslint/no-use-before-define": "error", + "@typescript-eslint/no-misused-promises": [ + "error", + { + checksVoidReturn: { + attributes: false, + }, + }, + ], + "no-shadow": "off", + "@typescript-eslint/no-shadow": "error", + "no-loop-func": "off", + "@typescript-eslint/no-loop-func": "error", + "no-useless-constructor": "off", + "@typescript-eslint/no-useless-constructor": "error", + "no-return-await": "off", + "@typescript-eslint/return-await": "error", + "@typescript-eslint/prefer-promise-reject-errors": ["off"], + + // Import + "import-x/no-extraneous-dependencies": [ + "error", + { + devDependencies: true, + }, + ], + // Some issues with react import, no time to debug + "import-x/default": ["off"], + + "prettier/prettier": "warn", + + // React + "react-hooks/exhaustive-deps": "error", + "react-refresh/only-export-components": "warn", + "react/jsx-no-duplicate-props": [ + "error", + { + ignoreCase: false, + }, + ], + + "react/prop-types": "off", + "react/react-in-jsx-scope": "off", + + // FormaJS/INTL + "formatjs/enforce-default-message": "error", + "formatjs/enforce-id": [ + "error", + { + idInterpolationPattern: "[sha1:contenthash:base64:6]", + }, + ], + "formatjs/no-id": "off", + }, + } +); diff --git a/flake.nix b/flake.nix index 16039ec..82aae0e 100644 --- a/flake.nix +++ b/flake.nix @@ -40,6 +40,8 @@ golangci-config-file = ./.golangci.yml; + eslint-config-file = ./eslint.config.mjs; + cd_root = "cd $PRJ_ROOT;"; control4_env = self.lib.forAllSystems (