import { Linter } from "eslint"; import { defineConfig, globalIgnores } from "eslint/config"; import globals from "globals"; import javascript from "@eslint/js"; import jsdoc from "eslint-plugin-jsdoc"; import oxlint from "eslint-plugin-oxlint"; import functional from "eslint-plugin-functional"; import typescriptEslint from "typescript-eslint"; import sonarJs from "eslint-plugin-sonarjs"; import perfectionist from "eslint-plugin-perfectionist"; import unicorn from "eslint-plugin-unicorn"; //#region règles/javascript.ts const règlesJavaScript = { name: "JavaScript", rules: { ...javascript.configs.recommended.rules, "array-callback-return": ["error", { allowVoid: true, checkForEach: true }], "no-nested-ternary": "off", "no-unassigned-vars": "error", "no-unneeded-ternary": ["error", { defaultAssignment: false }], "no-unreachable-loop": "error", "no-use-before-define": "off", "no-useless-assignment": "error", yoda: ["error", "never"] } }; //#endregion //#region règles/jsdoc.ts const flatRecommended = jsdoc.configs["flat/recommended-typescript"]; const flatStylistic = jsdoc.configs["flat/stylistic-typescript"]; const règlesJsDoc = { name: "JSDoc", plugins: flatRecommended.plugins ?? {}, rules: { ...flatRecommended.rules, ...flatStylistic.rules, "jsdoc/check-indentation": "warn", "jsdoc/check-line-alignment": "warn", "jsdoc/check-tag-names": ["warn", { definedTags: ["link"] }], "jsdoc/lines-before-block": "off", "jsdoc/no-blank-block-descriptions": "warn", "jsdoc/no-blank-blocks": "warn", "jsdoc/require-hyphen-before-param-description": ["warn", "never"], "jsdoc/require-throws": "warn", "jsdoc/sort-tags": "warn", "jsdoc/tag-lines": "off" } }; //#endregion //#region règles/oxlint.ts const règlesOxlint = { name: "Oxlint", ...oxlint.configs["flat/recommended"][0] }; //#endregion //#region règles/programmation-fonctionnelle.ts const règlesProgrammationFonctionnelle = { name: "Programmation fonctionnelle", plugins: { functional }, rules: { ...functional.configs.noExceptions.rules, ...functional.configs.noMutations.rules, ...functional.configs.externalTypeScriptRecommended.rules, ...functional.configs.stylistic.rules, "@typescript-eslint/array-type": ["error", { default: "generic", readonly: "generic" }], "functional/prefer-immutable-types": "off", "functional/prefer-tacit": "off", "functional/readonly-type": ["error", "generic"], "functional/type-declaration-immutability": "off" } }; //#endregion //#region règles/sonarjs.ts const règlesSonarJs = { name: "SonarJS", plugins: sonarJs.configs.recommended.plugins ?? {}, rules: { ...sonarJs.configs.recommended.rules, "sonarjs/arguments-usage": "error", "sonarjs/no-collapsible-if": "error", "sonarjs/no-duplicate-string": "error", "sonarjs/no-inconsistent-returns": "error", "sonarjs/no-nested-switch": "error", "sonarjs/prefer-immediate-return": "error" } }; //#endregion //#region règles/tri.ts const règlesTri = { name: "Tri", plugins: perfectionist.configs["recommended-natural"].plugins ?? {}, rules: perfectionist.configs["recommended-natural"].rules ?? {} }; //#endregion //#region règles/typescript.ts const trouveConfiguration = (configuration, nom) => configuration.find((v) => v.name === nom) ?? {}; const base = trouveConfiguration(typescriptEslint.configs.strictTypeChecked, "typescript-eslint/base"); const desactivationsJavaScript = trouveConfiguration(typescriptEslint.configs.strictTypeChecked, "typescript-eslint/eslint-recommended"); const strictTypeChecked = trouveConfiguration(typescriptEslint.configs.strictTypeChecked, "typescript-eslint/strict-type-checked"); const stylisticTypeChecked = trouveConfiguration(typescriptEslint.configs.stylisticTypeChecked, "typescript-eslint/stylistic-type-checked"); const règlesTypeScript = { languageOptions: base.languageOptions ?? {}, name: "TypeScript", plugins: base.plugins ?? {}, rules: { ...desactivationsJavaScript.rules, ...strictTypeChecked.rules, ...stylisticTypeChecked.rules, "@typescript-eslint/consistent-type-definitions": ["error", "type"], "@typescript-eslint/max-params": ["error", { max: 3 }], "@typescript-eslint/method-signature-style": ["off", "property"], "@typescript-eslint/no-magic-numbers": "off", "@typescript-eslint/no-unnecessary-boolean-literal-compare": "off", "@typescript-eslint/no-unnecessary-type-parameters": "off" } }; //#endregion //#region règles/unicorn.ts const règlesUnicorn = { name: "Unicorn", plugins: { unicorn }, rules: { ...unicorn.configs.unopinionated.rules, "unicorn/catch-error-name": "error", "unicorn/consistent-empty-array-spread": "error", "unicorn/custom-error-definition": "error", "unicorn/explicit-length-check": ["error", { "non-zero": "not-equal" }], "unicorn/no-array-for-each": "off", "unicorn/no-array-reduce": "off", "unicorn/no-negated-condition": "error", "unicorn/no-nested-ternary": "error", "unicorn/no-null": "error", "unicorn/prefer-dom-node-dataset": "off" } }; //#endregion //#region index.ts const configTypescriptNavigateur = defineConfig([ globalIgnores(["dist/**/*"], "Ignore le dossier de compilation"), { files: ["**/*.js", "**/*.ts"], name: "Fichiers à analyser" }, { languageOptions: { ecmaVersion: "latest", globals: { ...globals.browser, ...globals.builtin, ...globals.es2026, ...globals.node }, parserOptions: { ecmaVersion: "latest", projectService: true, sourceType: "module", tsconfigRootDir: import.meta.dirname } }, name: "Configuration du projet" }, règlesJavaScript, règlesTypeScript, règlesProgrammationFonctionnelle, règlesUnicorn, règlesSonarJs, règlesJsDoc, règlesTri, règlesOxlint ]); //#endregion export { configTypescriptNavigateur };