Deux angles morts fermés. 1. Syntaxe SQL sans conteneur (apps/api/test/sqlSyntax.test.js) Le faux pool vérifiait la FORME du SQL mais ne l'exécutait jamais : une requête syntaxiquement invalide passait tous les tests et n'échouait qu'en production — c'est précisément ce qui s'était produit avec crawler_pending. Chaque requête réellement émise par les 28 routes est désormais parsée avec la grammaire PostgreSQL (node-sql-parser), y compris les SET dynamiques du PATCH et les casts par type de resolve-conflict. 48 tests, aucun conteneur. Limite déclarée explicitement : la sémantique n'est pas validée, et deux requêtes bâties sur jsonb_build_object ne sont pas parsables — le test échoue si une route cesse d'avoir la moindre requête vérifiable, pour éviter qu'il passe au vert à vide. 2. Supervision des services de fond (migration 015) Le crawler et les workers ne sont pas exposés par Traefik : aucune sonde HTTP ne peut les atteindre. Un crawler dont FlareSolverr était injoignable, ou un worker à court de quota Geoapify, restait muet — le seul symptôme était l'absence de données nouvelles, qu'il fallait remarquer soi-même. Chaque service écrit un battement de cœur horaire dans service_health : - crawler : base, FlareSolverr joignable, dernier run terminé < 12 h - geocoder : base, clé Geoapify présente, API joignable, progression < 6 h Une ligne par service, écrasée à chaque contrôle. L'API calcule `stale` en SQL (> 2 h sans écriture) : un service arrêté cesse d'écrire, et son dernier contrôle réussi le ferait sinon passer pour sain indéfiniment. Le Pilotage affiche une carte « Services » et remonte chaque service dégradé ou silencieux en alerte actionnable. Règle appliquée aux sondes : aucune ne peut interrompre le service qu'elle surveille. Toute exception devient un échec de sonde, l'écriture du résultat et la journalisation échouent en silence. Un contrôle de santé qui fait tomber le crawler serait pire que pas de contrôle. Tests : 580 JS (+51), 63 Python (+20), 85 Playwright (+3) Co-Authored-By: Claude <noreply@anthropic.com>
53 lines
2.9 KiB
JSON
53 lines
2.9 KiB
JSON
{
|
|
"name": "metalfromeu",
|
|
"version": "0.0.1",
|
|
"private": true,
|
|
"type": "module",
|
|
"description": "Monorepo metalfrom.eu — outillage qualité (lint, types, tests). Chaque app garde son propre runtime.",
|
|
"workspaces": [
|
|
"apps/api"
|
|
],
|
|
"scripts": {
|
|
"lint": "eslint . --cache --cache-location node_modules/.cache/eslint/",
|
|
"lint:fix": "eslint . --fix --cache --cache-location node_modules/.cache/eslint/",
|
|
"typecheck": "tsc -p jsconfig.json",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest",
|
|
"test:cov": "vitest run --coverage",
|
|
"test:mutation": "stryker run",
|
|
"test:mutation:full": "stryker run stryker.full.config.json",
|
|
"lint:py": "ruff check .",
|
|
"lint:py:fix": "ruff check . --fix",
|
|
"test:py": "npm run test:py:geocoder && npm run test:py:crawler",
|
|
"test:py:geocoder": "cd apps/geocoder && python -m pytest tests -q",
|
|
"test:py:crawler": "cd apps/crawler && python -m pytest tests -q",
|
|
"audit:js": "npm audit --audit-level=high",
|
|
"audit:py": "pip-audit -r apps/api/../crawler/requirements.txt -r apps/geocoder/requirements.txt",
|
|
"_comment_check": "`check` = la porte de qualite lancee avant chaque push. Les cinq verifications tournent en parallele (voir scripts/check.mjs). Mutation et audits de dependances en sont exclus : trop lents / dependants du reseau — voir `check:full`.",
|
|
"check": "node scripts/check.mjs",
|
|
"check:full": "npm run check && npm run test:e2e && npm run audit:js && npm run audit:py && npm run test:mutation:full",
|
|
"hooks:install": "git config core.hooksPath .githooks",
|
|
"_comment_cache": "lint et typecheck utilisent un cache dans node_modules/.cache : `check` tourne des dizaines de fois par jour, refaire l'analyse complete de fichiers inchanges a chaque fois n'apporte rien. Les caches sont invalides par mtime+contenu ; `npm run check:clean` les purge.",
|
|
"check:clean": "node -e \"require('fs').rmSync('node_modules/.cache',{recursive:true,force:true})\"",
|
|
"check:sequential": "node scripts/check.mjs --sequential",
|
|
"test:e2e": "playwright test",
|
|
"test:e2e:ui": "playwright test --ui",
|
|
"test:e2e:install": "playwright install chromium",
|
|
"_comment_e2e": "Les parcours Playwright (~22 s) ne sont PAS dans `check` : celui-ci tourne des dizaines de fois par jour et doit rester sous 10 s. Ils sont lances par le hook pre-push, granularite correcte pour ce cout. `npm run test:e2e:install` recupere Chromium sur un clone neuf."
|
|
},
|
|
"devDependencies": {
|
|
"@axe-core/playwright": "^4.13.0",
|
|
"@eslint/js": "^9.17.0",
|
|
"@playwright/test": "^1.62.1",
|
|
"@stryker-mutator/core": "^8.7.1",
|
|
"@stryker-mutator/vitest-runner": "^8.7.1",
|
|
"@vitest/coverage-v8": "^2.1.8",
|
|
"axe-core": "^4.10.2",
|
|
"eslint": "^9.17.0",
|
|
"globals": "^15.14.0",
|
|
"jsdom": "^25.0.1",
|
|
"node-sql-parser": "^5.4.0",
|
|
"typescript": "^5.7.2",
|
|
"vitest": "^2.1.8"
|
|
}
|
|
}
|