`npm run check` échouait par intermittence sur : Error: ENOENT: no such file or directory, open 'vitest.config.js.timestamp-1787150578770-50269fd6fd11e.mjs' Vitest écrit une version transpilée de sa config à côté d'elle au démarrage, puis la supprime aussitôt. Depuis que les vérifications tournent en parallèle, ESLint apercevait ce fichier pendant son balayage et il avait disparu au moment de le lire. Course non déterministe : elle ne se déclenchait que si les deux tâches se croisaient au mauvais instant, d'où un gate qui échoue sans raison apparente un push sur trois — le pire mode de défaillance pour une porte de qualité, puisqu'il pousse à utiliser --no-verify par réflexe. Motif ajouté aux ignores. Trois exécutions consécutives vertes.
126 lines
4.4 KiB
JavaScript
126 lines
4.4 KiB
JavaScript
import js from "@eslint/js";
|
|
import globals from "globals";
|
|
|
|
/**
|
|
* Config ESLint « flat » (ESLint 9).
|
|
*
|
|
* Trois environnements coexistent dans ce repo et n'ont pas les mêmes globales :
|
|
* - apps/api : Node ESM
|
|
* - apps/web/site : scripts classiques navigateur (Leaflet en global)
|
|
* - apps/admin/site : scripts classiques navigateur
|
|
*/
|
|
export default [
|
|
{
|
|
ignores: [
|
|
"**/node_modules/**",
|
|
"apps/web/quizz-site/**",
|
|
"reports/**",
|
|
".stryker-tmp/**",
|
|
"coverage/**",
|
|
// Vitest écrit une version transpilée de sa config à côté d'elle
|
|
// (vitest.config.js.timestamp-XXXX.mjs) puis la supprime aussitôt.
|
|
// ESLint et Vitest tournant en parallèle dans `npm run check`, ESLint
|
|
// apercevait ce fichier au balayage et échouait en ENOENT au moment de
|
|
// le lire. Course non déterministe : elle ne se déclenchait que si les
|
|
// deux tâches se croisaient au mauvais moment.
|
|
"**/*.timestamp-*.mjs",
|
|
],
|
|
},
|
|
|
|
js.configs.recommended,
|
|
|
|
// ---- API : Node, ESM ----
|
|
{
|
|
files: ["apps/api/src/**/*.js"],
|
|
languageOptions: {
|
|
ecmaVersion: 2023,
|
|
sourceType: "module",
|
|
globals: { ...globals.node },
|
|
},
|
|
rules: {
|
|
"no-unused-vars": ["error", { argsIgnorePattern: "^_", caughtErrors: "none" }],
|
|
"no-console": "off",
|
|
eqeqeq: ["error", "smart"],
|
|
"prefer-const": "error",
|
|
"no-var": "error",
|
|
"no-throw-literal": "error",
|
|
// require-await est inadapté à Fastify : un handler `async` sans `await`
|
|
// est la façon NORMALE de renvoyer une valeur (l'API distingue le style
|
|
// async du style callback avec reply.send). Le rendre synchrone
|
|
// changerait la sémantique. La règle produisait 7 avertissements
|
|
// permanents — et un gate qui affiche toujours la même chose finit par
|
|
// ne plus être lu.
|
|
"require-await": "off",
|
|
},
|
|
},
|
|
|
|
// ---- Tests (vitest + Playwright). Certains tournent sous jsdom ou dans un
|
|
// navigateur → globales navigateur en plus de Node. Le harnais e2e est en
|
|
// .mjs (modules ES chargés directement par node). ----
|
|
{
|
|
files: ["apps/*/test/**/*.{js,mjs}"],
|
|
languageOptions: {
|
|
ecmaVersion: 2023,
|
|
sourceType: "module",
|
|
globals: { ...globals.node, ...globals.browser },
|
|
},
|
|
rules: {
|
|
"no-unused-vars": ["error", { argsIgnorePattern: "^_", caughtErrors: "none" }],
|
|
},
|
|
},
|
|
|
|
// ---- Frontends : scripts classiques navigateur ----
|
|
{
|
|
files: ["apps/web/site/**/*.js", "apps/admin/site/**/*.js"],
|
|
languageOptions: {
|
|
ecmaVersion: 2023,
|
|
sourceType: "script",
|
|
globals: {
|
|
...globals.browser,
|
|
// Chargés via <script> (CDN ou fichier local) avant app.js
|
|
L: "readonly",
|
|
LOCALES: "readonly",
|
|
noUiSlider: "readonly",
|
|
BMPure: "readonly",
|
|
// Footer CJS des modules « purs » partagés navigateur/test
|
|
module: "writable",
|
|
},
|
|
},
|
|
rules: {
|
|
"no-unused-vars": ["error", { argsIgnorePattern: "^_", caughtErrors: "none" }],
|
|
// `try { … } catch {}` volontaire sur les appels best-effort (logout, télémétrie)
|
|
"no-empty": ["error", { allowEmptyCatch: true }],
|
|
// Les console.log du site public sont des traces de diagnostic voulues
|
|
// par l'auteur. Les signaler à chaque exécution sans jamais les retirer
|
|
// ne fait que noyer les vrais avertissements. Si on décide un jour de
|
|
// les supprimer, remettre ["warn", { allow: ["warn", "error"] }].
|
|
"no-console": "off",
|
|
eqeqeq: ["error", "smart"],
|
|
"prefer-const": "error",
|
|
"no-var": "error",
|
|
// Les frontends déclarent volontairement des globales partagées entre fichiers
|
|
"no-redeclare": ["error", { builtinGlobals: false }],
|
|
},
|
|
},
|
|
|
|
// ---- Traductions : les espaces insécables fines sont de la typographie
|
|
// volontaire (français, tchèque…), pas des caractères parasites. ----
|
|
{
|
|
files: ["apps/web/site/locales.js"],
|
|
rules: { "no-irregular-whitespace": "off" },
|
|
},
|
|
|
|
// ---- Config et scripts d'outillage (racine + scripts/) ----
|
|
{
|
|
files: ["*.js", "*.config.js", "scripts/**/*.{js,mjs}"],
|
|
languageOptions: {
|
|
ecmaVersion: 2023,
|
|
sourceType: "module",
|
|
globals: { ...globals.node },
|
|
},
|
|
rules: {
|
|
"no-unused-vars": ["error", { argsIgnorePattern: "^_", caughtErrors: "none" }],
|
|
"no-console": "off",
|
|
},
|
|
},
|
|
];
|