diff --git a/bun.lock b/bun.lock index a10b341..8caf990 100644 --- a/bun.lock +++ b/bun.lock @@ -5,6 +5,11 @@ "": { "name": "@gcch/configuration-oxlint", "dependencies": { + "eslint-plugin-astro": "^1.6.0", + "eslint-plugin-functional": "^9.0.4", + "eslint-plugin-jsx-a11y": "^6.10.2", + "eslint-plugin-perfectionist": "^5.8.0", + "eslint-plugin-sonarjs": "^4.0.2", "globals": "^17.4.0", "oxlint": "^1.58.0", "oxlint-tsgolint": "^0.19.0", @@ -14,25 +19,18 @@ "@gcch/configuration-eslint": "git+https://git.gcch.fr/gcch/configuration-eslint#c0620280e6", "@gcch/configuration-prettier": "git+https://git.gcch.fr/gcch/configuration-prettier#91d4573bff", "@types/bun": "^1.3.11", - "@types/node": "^25.5.0", - "eslint-plugin-functional": "^9.0.4", - "eslint-plugin-jsx-a11y": "^6.10.2", - "eslint-plugin-perfectionist": "^5.7.0", - "eslint-plugin-sonarjs": "^4.0.2", - "knip": "^6.1.1", + "@types/node": "^25.5.2", + "knip": "^6.3.0", "prettier": "^3.8.1", "publint": "^0.3.18", "tsdown": "^0.21.7", "typescript": "^6.0.2", }, - "optionalDependencies": { - "eslint-plugin-astro": "^1.6.0", - }, "peerDependencies": { "eslint-plugin-astro": "^1.6.0", "eslint-plugin-functional": "^9.0.4", "eslint-plugin-jsx-a11y": "^6.10.2", - "eslint-plugin-perfectionist": "^5.7.0", + "eslint-plugin-perfectionist": "^5.8.0", "eslint-plugin-sonarjs": "^4.0.2", "oxlint": "^1.58.0", "oxlint-tsgolint": "^0.19.0", @@ -314,7 +312,7 @@ "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="], + "@types/node": ["@types/node@25.5.2", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg=="], "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], @@ -498,7 +496,7 @@ "eslint-plugin-jsx-a11y": ["eslint-plugin-jsx-a11y@6.10.2", "", { "dependencies": { "aria-query": "^5.3.2", "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", "axe-core": "^4.10.0", "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "safe-regex-test": "^1.0.3", "string.prototype.includes": "^2.0.1" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q=="], - "eslint-plugin-perfectionist": ["eslint-plugin-perfectionist@5.7.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.57.1", "natural-orderby": "^5.0.0" }, "peerDependencies": { "eslint": "^8.45.0 || ^9.0.0 || ^10.0.0" } }, "sha512-WRHj7OZS/INutQ/gKN5C1ZGnMhkQ3oKZQAA2I7rl5yM8keBtSd9oj/qlJaHuwh5873FhMPqYlttcadF0YsTN7g=="], + "eslint-plugin-perfectionist": ["eslint-plugin-perfectionist@5.8.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.58.0", "natural-orderby": "^5.0.0" }, "peerDependencies": { "eslint": "^8.45.0 || ^9.0.0 || ^10.0.0" } }, "sha512-k8uIptWIxkUclonCFGyDzgYs9NI+Qh0a7cUXS3L7IYZDEsjXuimFBVbxXPQQngWqMiaxJRwbtYB4smMGMqF+cw=="], "eslint-plugin-sonarjs": ["eslint-plugin-sonarjs@4.0.2", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "builtin-modules": "^3.3.0", "bytes": "^3.1.2", "functional-red-black-tree": "^1.0.1", "globals": "^17.4.0", "jsx-ast-utils-x": "^0.1.0", "lodash.merge": "^4.6.2", "minimatch": "^10.2.4", "scslre": "^0.3.0", "semver": "^7.7.4", "ts-api-utils": "^2.4.0", "typescript": ">=5" }, "peerDependencies": { "eslint": "^8.0.0 || ^9.0.0 || ^10.0.0" } }, "sha512-BTcT1zr1iTbmJtVlcesISwnXzh+9uhf9LEOr+RRNf4kR8xA0HQTPft4oiyOCzCOGKkpSJxjR8ZYF6H7VPyplyw=="], @@ -678,7 +676,7 @@ "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], - "knip": ["knip@6.1.1", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "get-tsconfig": "4.13.7", "jiti": "^2.6.0", "minimist": "^1.2.8", "oxc-parser": "^0.121.0", "oxc-resolver": "^11.19.1", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.6.1", "strip-json-comments": "5.0.3", "unbash": "^2.2.0", "yaml": "^2.8.2", "zod": "^4.1.11" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-BC/kbdxwCgv+p/3YkGbtlLxbOXhQDuR+CeKKFEpJyKb3BFwG1gZa+CMWSqAnPi+kUexz74m327d3zWxyn2fMew=="], + "knip": ["knip@6.3.0", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "get-tsconfig": "4.13.7", "jiti": "^2.6.0", "minimist": "^1.2.8", "oxc-parser": "^0.121.0", "oxc-resolver": "^11.19.1", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.6.1", "strip-json-comments": "5.0.3", "unbash": "^2.2.0", "yaml": "^2.8.2", "zod": "^4.1.11" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-g6dVPoTw6iNm3cubC5IWxVkVsd0r5hXhTBTbAGIEQN53GdA2ZM/slMTPJ7n5l8pBebNQPHpxjmKxuR4xVQ2/hQ=="], "language-subtag-registry": ["language-subtag-registry@0.3.23", "", {}, "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ=="], @@ -1006,12 +1004,16 @@ "@eslint/config-array/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], + "@gcch/configuration-eslint/eslint-plugin-perfectionist": ["eslint-plugin-perfectionist@5.7.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.57.1", "natural-orderby": "^5.0.0" }, "peerDependencies": { "eslint": "^8.45.0 || ^9.0.0 || ^10.0.0" } }, "sha512-WRHj7OZS/INutQ/gKN5C1ZGnMhkQ3oKZQAA2I7rl5yM8keBtSd9oj/qlJaHuwh5873FhMPqYlttcadF0YsTN7g=="], + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], + "bun-types/@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="], + "clean-regexp/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], "eslint/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], @@ -1030,6 +1032,8 @@ "eslint-plugin-jsdoc/espree": ["espree@11.2.0", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw=="], + "eslint-plugin-perfectionist/@typescript-eslint/utils": ["@typescript-eslint/utils@8.58.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA=="], + "eslint-plugin-sonarjs/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], @@ -1050,6 +1054,12 @@ "eslint-plugin-jsdoc/espree/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0" } }, "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.58.0", "", {}, "sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.58.0", "@typescript-eslint/tsconfig-utils": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA=="], + "eslint-plugin-sonarjs/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], "eslint/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], @@ -1058,8 +1068,26 @@ "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.0", "@typescript-eslint/types": "^8.58.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], + "eslint-plugin-sonarjs/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "eslint/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], + + "eslint-plugin-perfectionist/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], } } diff --git a/cfg/eslint.config.ts b/cfg/eslint.config.ts index 8f223cc..f918764 100644 --- a/cfg/eslint.config.ts +++ b/cfg/eslint.config.ts @@ -1,4 +1,6 @@ import { configAstro } from "@gcch/configuration-eslint"; import { defineConfig } from "eslint/config"; -export default defineConfig([...configAstro]); +const config = defineConfig([...configAstro]); + +export default config; diff --git a/cfg/oxlint.config.ts b/cfg/oxlint.config.ts index 693b2c2..5ad209c 100644 --- a/cfg/oxlint.config.ts +++ b/cfg/oxlint.config.ts @@ -1,3 +1,3 @@ -import config from "../index"; +import config from "../index.ts"; export default config; diff --git a/cfg/tsdown.config.ts b/cfg/tsdown.config.ts index bd3eb15..f3b8735 100644 --- a/cfg/tsdown.config.ts +++ b/cfg/tsdown.config.ts @@ -1,13 +1,16 @@ import type { UserConfig } from "tsdown"; + import { defineConfig } from "tsdown"; const config: UserConfig = defineConfig({ + checks: { circularDependency: true }, clean: true, dts: { oxc: true, parallel: true }, entry: ["../index.ts"], minify: false, outDir: "../dist", platform: "node", + publint: true, sourcemap: false, target: "esnext", treeshake: true, diff --git a/dist/index.mjs b/dist/index.mjs index dd76cc7..002b316 100644 --- a/dist/index.mjs +++ b/dist/index.mjs @@ -68,17 +68,6 @@ const astroConfig = { }, }; -//#endregion -//#region ../rules/functional.ts -const functionalRules = { - "functional/immutable-data": "error", - "functional/no-let": "error", - "functional/no-throw-statements": "error", - "functional/no-try-statements": "error", - "functional/prefer-property-signatures": "error", - "functional/readonly-type": ["error", "generic"], -}; - //#endregion //#region ../rules/eslint.ts const esLintRules = { @@ -375,24 +364,304 @@ const esLintRules = { ], }; +//#endregion +//#region ../rules/functional.ts +const functionalRules = { + "functional/immutable-data": "error", + "functional/no-let": "error", + "functional/no-throw-statements": "error", + "functional/no-try-statements": "error", + "functional/prefer-property-signatures": "error", + "functional/readonly-type": ["error", "generic"], +}; + +//#endregion +//#region ../rules/import.ts +const importRules = { + "import/consistent-type-specifier-style": ["deny", "prefer-top-level"], + "import/default": "deny", + "import/export": "deny", + "import/exports-last": "deny", + "import/extensions": [ + "deny", + "always", + { + checkTypeImports: true, + ignorePackages: true, + }, + ], + "import/first": ["deny", "absolute-first"], + "import/group-exports": "deny", + "import/max-dependencies": "allow", + "import/named": "deny", + "import/namespace": ["deny", { allowComputed: false }], + "import/no-absolute-path": [ + "deny", + { + amd: false, + commonjs: true, + esmodule: true, + }, + ], + "import/no-amd": "deny", + "import/no-anonymous-default-export": [ + "deny", + { + allowAnonymousClass: false, + allowAnonymousFunction: false, + allowArray: false, + allowArrowFunction: false, + allowCallExpression: false, + allowLiteral: false, + allowNew: false, + allowObject: false, + }, + ], + "import/no-commonjs": [ + "deny", + { + allowConditionalRequire: false, + allowPrimitiveModules: false, + allowRequire: false, + }, + ], + "import/no-cycle": [ + "deny", + { + allowUnsafeDynamicCyclicDependency: false, + ignoreExternal: false, + ignoreTypes: true, + maxDepth: 4294967295, + }, + ], + "import/no-default-export": "allow", + "import/no-duplicates": [ + "deny", + { + considerQueryString: true, + preferInline: false, + }, + ], + "import/no-dynamic-require": ["deny", { esmodule: true }], + "import/no-empty-named-blocks": "deny", + "import/no-mutable-exports": "deny", + "import/no-named-as-default": "deny", + "import/no-named-as-default-member": "deny", + "import/no-named-default": "deny", + "import/no-named-export": "deny", + "import/no-namespace": "deny", + "import/no-nodejs-modules": "allow", + "import/no-relative-parent-imports": "allow", + "import/no-self-import": "deny", + "import/no-unassigned-import": "deny", + "import/no-webpack-loader-syntax": "deny", + "import/prefer-default-export": ["deny", { target: "single" }], + "import/unambiguous": "deny", +}; + //#endregion //#region ../rules/jsdoc.ts const jsDocRules = { "jsdoc/check-access": "warn", "jsdoc/check-property-names": "warn", - "jsdoc/check-tag-names": ["warn", { definedTags: ["link"] }], + "jsdoc/check-tag-names": [ + "warn", + { + definedTags: ["link"], + typed: true, + }, + ], "jsdoc/empty-tags": "warn", "jsdoc/implements-on-classes": "warn", - "jsdoc/no-defaults": "warn", - "jsdoc/require-param": "warn", + "jsdoc/no-defaults": ["warn", { noOptionalParamNames: true }], + "jsdoc/require-param": [ + "warn", + { + checkConstructors: true, + checkDestructured: true, + checkDestructuredRoots: true, + checkGetters: true, + checkRestProperty: true, + checkSetters: true, + }, + ], "jsdoc/require-param-description": "warn", "jsdoc/require-param-name": "warn", + "jsdoc/require-param-type": "warn", "jsdoc/require-property": "warn", "jsdoc/require-property-description": "warn", "jsdoc/require-property-name": "warn", - "jsdoc/require-returns": "warn", + "jsdoc/require-property-type": "warn", + "jsdoc/require-returns": [ + "warn", + { + checkConstructors: true, + checkGetters: true, + forceRequireReturn: true, + forceReturnsWithAsync: true, + }, + ], "jsdoc/require-returns-description": "warn", - "jsdoc/require-yields": "warn", + "jsdoc/require-returns-type": "warn", + "jsdoc/require-yields": [ + "warn", + { + forceRequireYields: false, + withGeneratorTag: false, + }, + ], +}; + +//#endregion +//#region ../rules/perfectionist.ts +const perfectionistRules = { + "perfectionist/sort-array-includes": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-classes": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-decorators": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-enums": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-export-attributes": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-exports": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-heritage-clauses": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-import-attributes": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-interfaces": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-intersection-types": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-jsx-props": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-maps": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-modules": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-named-exports": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-named-imports": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-object-types": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-objects": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-sets": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-switch-case": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-union-types": [ + "error", + { + order: "asc", + type: "natural", + }, + ], + "perfectionist/sort-variable-declarations": [ + "error", + { + order: "asc", + type: "natural", + }, + ], }; //#endregion @@ -610,158 +879,6 @@ const sonarJsRules = { "sonarjs/xml-parser-xxe": "error", }; -//#endregion -//#region ../rules/perfectionist.ts -const perfectionistRules = { - "perfectionist/sort-array-includes": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-classes": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-decorators": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-enums": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-export-attributes": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-exports": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-heritage-clauses": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-import-attributes": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-interfaces": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-intersection-types": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-jsx-props": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-maps": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-modules": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-named-exports": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-named-imports": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-object-types": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-objects": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-sets": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-switch-case": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-union-types": [ - "error", - { - order: "asc", - type: "natural", - }, - ], - "perfectionist/sort-variable-declarations": [ - "error", - { - order: "asc", - type: "natural", - }, - ], -}; - //#endregion //#region ../rules/typescript.ts const typeScriptRules = { @@ -990,6 +1107,95 @@ const unicornRules = { "unicorn/throw-new-error": "error", }; +//#endregion +//#region ../rules/node.ts +const nodeRules = { + "node/global-require": "deny", + "node/handle-callback-err": "allow", + "node/no-exports-assign": "deny", + "node/no-new-require": "deny", + "node/no-path-concat": "deny", + "node/no-process-env": "deny", +}; + +//#endregion +//#region ../rules/oxc.ts +const oxcRules = { + "oxc/approx-constant": "deny", + "oxc/bad-array-method-on-arguments": "deny", + "oxc/bad-bitwise-operator": "deny", + "oxc/bad-char-at-comparison": "deny", + "oxc/bad-comparison-sequence": "deny", + "oxc/bad-min-max-func": "deny", + "oxc/bad-object-literal-comparison": "deny", + "oxc/bad-replace-all-arg": "deny", + "oxc/branches-sharing-code": "warn", + "oxc/const-comparisons": "deny", + "oxc/double-comparisons": "deny", + "oxc/erasing-op": "deny", + "oxc/misrefactored-assign-op": "deny", + "oxc/missing-throw": "deny", + "oxc/no-accumulating-spread": "deny", + "oxc/no-async-await": "allow", + "oxc/no-async-endpoint-handlers": "allow", + "oxc/no-barrel-file": ["deny", { threshold: 100 }], + "oxc/no-const-enum": "deny", + "oxc/no-map-spread": "allow", + "oxc/no-optional-chaining": "allow", + "oxc/no-rest-spread-properties": "allow", + "oxc/no-this-in-exported-function": "deny", + "oxc/number-arg-out-of-range": "deny", + "oxc/only-used-in-recursion": "deny", + "oxc/uninvoked-array-callback": "deny", +}; + +//#endregion +//#region ../rules/promise.ts +const promiseRules = { + "promise/always-return": [ + "deny", + { + ignoreAssignmentVariable: ["globalThis"], + ignoreLastCallback: false, + }, + ], + "promise/avoid-new": "deny", + "promise/catch-or-return": [ + "deny", + { + allowFinally: false, + allowThen: false, + terminationMethod: ["catch"], + }, + ], + "promise/no-callback-in-promise": [ + "deny", + { + callbacks: ["callback", "cb", "done", "next"], + exceptions: [], + timeoutsErr: false, + }, + ], + "promise/no-multiple-resolved": "deny", + "promise/no-nesting": "deny", + "promise/no-new-statics": "deny", + "promise/no-promise-in-callback": "deny", + "promise/no-return-in-finally": "deny", + "promise/no-return-wrap": ["deny", { allowReject: false }], + "promise/param-names": [ + "deny", + { + rejectPattern: "^_?reject$", + resolvePattern: "^_?resolve$", + }, + ], + "promise/prefer-await-to-callbacks": "deny", + "promise/prefer-await-to-then": ["deny", { strict: true }], + "promise/prefer-catch": "deny", + "promise/spec-only": ["deny", { allowedMethods: [] }], + "promise/valid-params": "deny", +}; + //#endregion //#region ../index.ts const config = defineConfig({ @@ -1019,9 +1225,13 @@ const config = defineConfig({ rules: { ...esLintRules, ...functionalRules, + ...importRules, ...jsDocRules, - ...sonarJsRules, + ...nodeRules, + ...oxcRules, ...perfectionistRules, + ...promiseRules, + ...sonarJsRules, ...typeScriptRules, ...unicornRules, }, diff --git a/index.ts b/index.ts index cf0b2fe..ca6c80f 100644 --- a/index.ts +++ b/index.ts @@ -1,13 +1,18 @@ -import { defineConfig } from "oxlint"; import type { OxlintConfig } from "oxlint"; -import astroConfig from "./rules/astro"; -import functionalRules from "./rules/functional"; -import esLintRules from "./rules/eslint"; -import jsDocRules from "./rules/jsdoc"; -import sonarJsRules from "./rules/sonarjs"; -import perfectionistRules from "./rules/perfectionist"; -import typeScriptRules from "./rules/typescript"; -import unicornRules from "./rules/unicorn"; +import { defineConfig } from "oxlint"; + +import astroConfig from "./rules/astro.ts"; +import esLintRules from "./rules/eslint.ts"; +import functionalRules from "./rules/functional.ts"; +import importRules from "./rules/import.ts"; +import jsDocRules from "./rules/jsdoc.ts"; +import perfectionistRules from "./rules/perfectionist.ts"; +import sonarJsRules from "./rules/sonarjs.ts"; +import typeScriptRules from "./rules/typescript.ts"; +import unicornRules from "./rules/unicorn.ts"; +import nodeRules from "./rules/node.ts"; +import oxcRules from "./rules/oxc.ts"; +import promiseRules from "./rules/promise.ts"; const config: OxlintConfig = defineConfig({ categories: { @@ -36,9 +41,13 @@ const config: OxlintConfig = defineConfig({ rules: { ...esLintRules, ...functionalRules, + ...importRules, ...jsDocRules, - ...sonarJsRules, + ...nodeRules, + ...oxcRules, ...perfectionistRules, + ...promiseRules, + ...sonarJsRules, ...typeScriptRules, ...unicornRules, }, diff --git a/justfile b/justfile index 5fe63b9..b2cc575 100644 --- a/justfile +++ b/justfile @@ -48,3 +48,7 @@ clean: rm -rf bun.lock rm -rf node_modules/ rm -rfv dist/ + +# Teste les règles à la mise à jour des fichiers sources. +watch: + watchexec --watch "./rules/" just build lint-js diff --git a/package.json b/package.json index c109853..8f15a84 100644 --- a/package.json +++ b/package.json @@ -15,32 +15,29 @@ "eslint-plugin-astro": "^1.6.0", "eslint-plugin-functional": "^9.0.4", "eslint-plugin-jsx-a11y": "^6.10.2", - "eslint-plugin-perfectionist": "^5.7.0", + "eslint-plugin-perfectionist": "^5.8.0", "eslint-plugin-sonarjs": "^4.0.2", "oxlint": "^1.58.0", "oxlint-tsgolint": "^0.19.0", "typescript": "^6.0.2" }, "dependencies": { + "eslint-plugin-astro": "^1.6.0", + "eslint-plugin-functional": "^9.0.4", + "eslint-plugin-jsx-a11y": "^6.10.2", + "eslint-plugin-perfectionist": "^5.8.0", + "eslint-plugin-sonarjs": "^4.0.2", "globals": "^17.4.0", "oxlint": "^1.58.0", "oxlint-tsgolint": "^0.19.0" }, - "optionalDependencies": { - "eslint-plugin-astro": "^1.6.0" - }, "devDependencies": { "@arethetypeswrong/core": "^0.18.2", "@gcch/configuration-eslint": "git+https://git.gcch.fr/gcch/configuration-eslint#c0620280e6", "@gcch/configuration-prettier": "git+https://git.gcch.fr/gcch/configuration-prettier#91d4573bff", "@types/bun": "^1.3.11", - "@types/node": "^25.5.0", - "eslint-plugin-astro": "^1.6.0", - "eslint-plugin-functional": "^9.0.4", - "eslint-plugin-jsx-a11y": "^6.10.2", - "eslint-plugin-perfectionist": "^5.7.0", - "eslint-plugin-sonarjs": "^4.0.2", - "knip": "^6.1.1", + "@types/node": "^25.5.2", + "knip": "^6.3.0", "prettier": "^3.8.1", "publint": "^0.3.18", "tsdown": "^0.21.7", diff --git a/rules/import.ts b/rules/import.ts new file mode 100644 index 0000000..b35d6df --- /dev/null +++ b/rules/import.ts @@ -0,0 +1,101 @@ +import type { DummyRuleMap } from "oxlint"; + +const importRules: DummyRuleMap = { + "import/consistent-type-specifier-style": ["deny", "prefer-top-level"], + "import/default": "deny", + "import/export": "deny", + "import/exports-last": "deny", + "import/extensions": [ + "deny", + "always", + { + checkTypeImports: true, + ignorePackages: true, + }, + ], + "import/first": ["deny", "absolute-first"], + "import/group-exports": "deny", + "import/max-dependencies": "allow", + "import/named": "deny", + "import/namespace": [ + "deny", + { + allowComputed: false, + }, + ], + "import/no-absolute-path": [ + "deny", + { + amd: false, + commonjs: true, + esmodule: true, + }, + ], + "import/no-amd": "deny", + "import/no-anonymous-default-export": [ + "deny", + { + allowAnonymousClass: false, + allowAnonymousFunction: false, + allowArray: false, + allowArrowFunction: false, + allowCallExpression: false, + allowLiteral: false, + allowNew: false, + allowObject: false, + }, + ], + "import/no-commonjs": [ + "deny", + { + allowConditionalRequire: false, + allowPrimitiveModules: false, + allowRequire: false, + }, + ], + "import/no-cycle": [ + "deny", + { + allowUnsafeDynamicCyclicDependency: false, + ignoreExternal: false, + ignoreTypes: true, + maxDepth: 4_294_967_295, + }, + ], + // J'aime les exports par défaut. + "import/no-default-export": "allow", + "import/no-duplicates": [ + "deny", + { + considerQueryString: true, + preferInline: false, + }, + ], + "import/no-dynamic-require": [ + "deny", + { + esmodule: true, + }, + ], + "import/no-empty-named-blocks": "deny", + "import/no-mutable-exports": "deny", + "import/no-named-as-default": "deny", + "import/no-named-as-default-member": "deny", + "import/no-named-default": "deny", + "import/no-named-export": "deny", + "import/no-namespace": "deny", + "import/no-nodejs-modules": "allow", + "import/no-relative-parent-imports": "allow", + "import/no-self-import": "deny", + "import/no-unassigned-import": "deny", + "import/no-webpack-loader-syntax": "deny", + "import/prefer-default-export": [ + "deny", + { + target: "single", + }, + ], + "import/unambiguous": "deny", +}; + +export default importRules; diff --git a/rules/jsdoc.ts b/rules/jsdoc.ts index 937112c..63d5056 100644 --- a/rules/jsdoc.ts +++ b/rules/jsdoc.ts @@ -7,20 +7,48 @@ const jsDocRules: DummyRuleMap = { "warn", { definedTags: ["link"], + typed: true, }, ], "jsdoc/empty-tags": "warn", "jsdoc/implements-on-classes": "warn", - "jsdoc/no-defaults": "warn", - "jsdoc/require-param": "warn", + "jsdoc/no-defaults": ["warn", { noOptionalParamNames: true }], + "jsdoc/require-param": [ + "warn", + { + checkConstructors: true, + checkDestructured: true, + checkDestructuredRoots: true, + checkGetters: true, + checkRestProperty: true, + checkSetters: true, + }, + ], "jsdoc/require-param-description": "warn", "jsdoc/require-param-name": "warn", + "jsdoc/require-param-type": "warn", "jsdoc/require-property": "warn", "jsdoc/require-property-description": "warn", "jsdoc/require-property-name": "warn", - "jsdoc/require-returns": "warn", + "jsdoc/require-property-type": "warn", + "jsdoc/require-returns": [ + "warn", + { + checkConstructors: true, + checkGetters: true, + forceRequireReturn: true, + forceReturnsWithAsync: true, + }, + ], "jsdoc/require-returns-description": "warn", - "jsdoc/require-yields": "warn", + "jsdoc/require-returns-type": "warn", + "jsdoc/require-yields": [ + "warn", + { + forceRequireYields: false, + withGeneratorTag: false, + }, + ], }; export default jsDocRules; diff --git a/rules/node.ts b/rules/node.ts new file mode 100644 index 0000000..c283db1 --- /dev/null +++ b/rules/node.ts @@ -0,0 +1,12 @@ +import type { DummyRuleMap } from "oxlint"; + +const nodeRules: DummyRuleMap = { + "node/global-require": "deny", + "node/handle-callback-err": "allow", + "node/no-exports-assign": "deny", + "node/no-new-require": "deny", + "node/no-path-concat": "deny", + "node/no-process-env": "deny", +}; + +export default nodeRules; diff --git a/rules/oxc.ts b/rules/oxc.ts new file mode 100644 index 0000000..1a28ae9 --- /dev/null +++ b/rules/oxc.ts @@ -0,0 +1,35 @@ +import type { DummyRuleMap } from "oxlint"; + +const oxcRules: DummyRuleMap = { + "oxc/approx-constant": "deny", + "oxc/bad-array-method-on-arguments": "deny", + "oxc/bad-bitwise-operator": "deny", + "oxc/bad-char-at-comparison": "deny", + "oxc/bad-comparison-sequence": "deny", + "oxc/bad-min-max-func": "deny", + "oxc/bad-object-literal-comparison": "deny", + "oxc/bad-replace-all-arg": "deny", + "oxc/branches-sharing-code": "warn", + "oxc/const-comparisons": "deny", + "oxc/double-comparisons": "deny", + "oxc/erasing-op": "deny", + "oxc/misrefactored-assign-op": "deny", + "oxc/missing-throw": "deny", + "oxc/no-accumulating-spread": "deny", + // This rule should generally not be used in modern JavaScript/TypeScript codebases without good reason. + "oxc/no-async-await": "allow", + "oxc/no-async-endpoint-handlers": "allow", + "oxc/no-barrel-file": ["deny", { threshold: 100 }], + "oxc/no-const-enum": "deny", + "oxc/no-map-spread": "allow", + // In most codebases at this point, you should not use this rule. + "oxc/no-optional-chaining": "allow", + // In most codebases at this point, you should not use this rule. + "oxc/no-rest-spread-properties": "allow", + "oxc/no-this-in-exported-function": "deny", + "oxc/number-arg-out-of-range": "deny", + "oxc/only-used-in-recursion": "deny", + "oxc/uninvoked-array-callback": "deny", +}; + +export default oxcRules; diff --git a/rules/promise.ts b/rules/promise.ts new file mode 100644 index 0000000..37385bf --- /dev/null +++ b/rules/promise.ts @@ -0,0 +1,53 @@ +import type { DummyRuleMap } from "oxlint"; + +const promiseRules: DummyRuleMap = { + "promise/always-return": [ + "deny", + { + ignoreAssignmentVariable: ["globalThis"], + ignoreLastCallback: false, + }, + ], + "promise/avoid-new": "deny", + "promise/catch-or-return": [ + "deny", + { + allowFinally: false, + allowThen: false, + terminationMethod: ["catch"], + }, + ], + "promise/no-callback-in-promise": [ + "deny", + { + callbacks: ["callback", "cb", "done", "next"], + exceptions: [], + timeoutsErr: false, + }, + ], + "promise/no-multiple-resolved": "deny", + "promise/no-nesting": "deny", + "promise/no-new-statics": "deny", + "promise/no-promise-in-callback": "deny", + "promise/no-return-in-finally": "deny", + "promise/no-return-wrap": [ + "deny", + { + allowReject: false, + }, + ], + "promise/param-names": [ + "deny", + { + rejectPattern: "^_?reject$", + resolvePattern: "^_?resolve$", + }, + ], + "promise/prefer-await-to-callbacks": "deny", + "promise/prefer-await-to-then": ["deny", { strict: true }], + "promise/prefer-catch": "deny", + "promise/spec-only": ["deny", { allowedMethods: [] }], + "promise/valid-params": "deny", +}; + +export default promiseRules;