@nodefony/devkit 10.0.0-alpha.6 → 10.0.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/decorate.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/decorateMetadata.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/decorateParam.js +1 -1
- package/dist/index.js +2 -2
- package/dist/nodefony/controllers/DevkitController.js +2 -2
- package/dist/nodefony/controllers/McpController.js +3 -3
- package/dist/nodefony/service/DevkitService.js +2 -2
- package/package.json +8 -8
- package/skills/nodefony-add-crud/SKILL.md +9 -0
- package/skills/nodefony-add-realtime-channel/SKILL.md +9 -0
- package/skills/nodefony-add-service/SKILL.md +9 -0
- package/skills/nodefony-browser/SKILL.md +19 -16
- package/skills/nodefony-dev/SKILL.md +273 -0
- package/skills/nodefony-dev/scripts/docs.mjs +544 -0
- package/skills/nodefony-devops/SKILL.md +198 -0
- package/skills/nodefony-devops/references/compose.md +125 -0
- package/skills/nodefony-devops/references/frontal.md +119 -0
- package/skills/nodefony-devops/references/image.md +136 -0
- package/skills/nodefony-devops/references/kubernetes.md +189 -0
- package/skills/nodefony-devops/references/podman.md +103 -0
- package/skills/nodefony-devops/references/secrets.md +108 -0
- package/skills/nodefony-devops/references/variables.md +174 -0
- package/skills/nodefony-migrate-schema/SKILL.md +29 -17
- package/skills/nodefony-protect-route/SKILL.md +9 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region \0@oxc-project+runtime@0.
|
|
1
|
+
//#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorate.js
|
|
2
2
|
function __decorate(decorators, target, key, desc) {
|
|
3
3
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
4
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region \0@oxc-project+runtime@0.
|
|
1
|
+
//#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorateMetadata.js
|
|
2
2
|
function __decorateMetadata(k, v) {
|
|
3
3
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
4
4
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import defaults, { devkitConfigSchema } from "./nodefony/config/config.js";
|
|
2
2
|
import { defineDevkitConfig } from "./nodefony/config/defineModuleConfig.js";
|
|
3
3
|
import { buildCard } from "./nodefony/src/card.js";
|
|
4
|
-
import __decorateMetadata from "./_virtual/_@oxc-project_runtime@0.
|
|
5
|
-
import __decorate from "./_virtual/_@oxc-project_runtime@0.
|
|
4
|
+
import __decorateMetadata from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
|
|
5
|
+
import __decorate from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
|
|
6
6
|
import DevkitService_default from "./nodefony/service/DevkitService.js";
|
|
7
7
|
import DevkitController_default from "./nodefony/controllers/DevkitController.js";
|
|
8
8
|
import McpController_default from "./nodefony/controllers/McpController.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import __decorate from "../../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import __decorate from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
|
|
3
3
|
import { Controller, controller, route } from "@nodefony/framework";
|
|
4
4
|
//#region nodefony/controllers/DevkitController.ts
|
|
5
5
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import __decorate from "../../_virtual/_@oxc-project_runtime@0.
|
|
3
|
-
import __decorateParam from "../../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import __decorate from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
|
|
3
|
+
import __decorateParam from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateParam.js";
|
|
4
4
|
import { ACCESS_TOKEN_VERIFIER, JsonRpcError, Nodefony, authorizeProtectedResource, checkMcpAccess, collectMcpTools, handleMcpMessage, jsonRpcFailure, mcpCallerRoles, protectedResourceMetadataUrl, readBearerHeader } from "nodefony";
|
|
5
5
|
import { Body, Controller, Headers, controller, route } from "@nodefony/framework";
|
|
6
6
|
//#region nodefony/controllers/McpController.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import defaults from "../config/config.js";
|
|
2
2
|
import { buildCard } from "../src/card.js";
|
|
3
|
-
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.
|
|
4
|
-
import __decorate from "../../_virtual/_@oxc-project_runtime@0.
|
|
3
|
+
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
|
|
4
|
+
import __decorate from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
|
|
5
5
|
import { Module, Nodefony, Service, extend, injectable, mcpDeclaredScopes } from "nodefony";
|
|
6
6
|
//#region nodefony/service/DevkitService.ts
|
|
7
7
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodefony/devkit",
|
|
3
|
-
"version": "10.0.0-alpha.
|
|
3
|
+
"version": "10.0.0-alpha.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Outillage de développement d'une application Nodefony : carte de visite du projet et portes de découverte pour un agent de développement",
|
|
6
6
|
"author": "Christophe CAMENSULI <ccamensuli@gmail.com>",
|
|
@@ -25,17 +25,17 @@
|
|
|
25
25
|
"coverage": "vitest run --coverage"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@nodefony/framework": "^10.0.0-alpha.
|
|
29
|
-
"@nodefony/http": "^10.0.0-alpha.
|
|
30
|
-
"nodefony": "^10.0.0-alpha.
|
|
31
|
-
"zod": "^4.6.
|
|
28
|
+
"@nodefony/framework": "^10.0.0-alpha.7",
|
|
29
|
+
"@nodefony/http": "^10.0.0-alpha.7",
|
|
30
|
+
"nodefony": "^10.0.0-alpha.7",
|
|
31
|
+
"zod": "^4.6.5",
|
|
32
32
|
"playwright": "^1.50.0",
|
|
33
33
|
"lighthouse": "^13.0.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@nodefony/framework": "^10.0.0-alpha.
|
|
37
|
-
"@nodefony/http": "^10.0.0-alpha.
|
|
38
|
-
"nodefony": "^10.0.0-alpha.
|
|
36
|
+
"@nodefony/framework": "^10.0.0-alpha.7",
|
|
37
|
+
"@nodefony/http": "^10.0.0-alpha.7",
|
|
38
|
+
"nodefony": "^10.0.0-alpha.7"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"axe-core": "4.13.0",
|
|
@@ -17,6 +17,15 @@ description: >
|
|
|
17
17
|
|
|
18
18
|
# add-crud — une ressource complète, générée
|
|
19
19
|
|
|
20
|
+
> 🧭 **Tu es arrivé ici directement ? Charge aussi `nodefony-dev`** — il porte la conduite
|
|
21
|
+
> commune (par où commencer, comment prouver que c'est fait) et les pièges qui coûtent une heure,
|
|
22
|
+
> serveur comme front. Cette page-ci ne couvre QUE son geste.
|
|
23
|
+
>
|
|
24
|
+
> Et si une réponse te manque, elle est probablement INSTALLÉE : `rg` ne descend pas dans
|
|
25
|
+
> `node_modules`, donc 70 pages de documentation y paraissent absentes. Une commande les lit, avec
|
|
26
|
+
> la ligne exacte :
|
|
27
|
+
> `node node_modules/@nodefony/devkit/skills/nodefony-dev/scripts/docs.mjs <termes>`.
|
|
28
|
+
|
|
20
29
|
> ⚖️ **La confiance n'exclut pas le contrôle.** Ce que le générateur produit se relit ;
|
|
21
30
|
> ce que tu écris à la main se prouve par un test.
|
|
22
31
|
|
|
@@ -13,6 +13,15 @@ description: >
|
|
|
13
13
|
|
|
14
14
|
# add-realtime-channel — le temps réel par sa couche
|
|
15
15
|
|
|
16
|
+
> 🧭 **Tu es arrivé ici directement ? Charge aussi `nodefony-dev`** — il porte la conduite
|
|
17
|
+
> commune (par où commencer, comment prouver que c'est fait) et les pièges qui coûtent une heure,
|
|
18
|
+
> serveur comme front. Cette page-ci ne couvre QUE son geste.
|
|
19
|
+
>
|
|
20
|
+
> Et si une réponse te manque, elle est probablement INSTALLÉE : `rg` ne descend pas dans
|
|
21
|
+
> `node_modules`, donc 70 pages de documentation y paraissent absentes. Une commande les lit, avec
|
|
22
|
+
> la ligne exacte :
|
|
23
|
+
> `node node_modules/@nodefony/devkit/skills/nodefony-dev/scripts/docs.mjs <termes>`.
|
|
24
|
+
|
|
16
25
|
> ⚖️ **La confiance n'exclut pas le contrôle.** Un canal sans politique est **public par
|
|
17
26
|
> construction** — c'est le comportement voulu du framework, pas un oubli. Ce qui n'est pas
|
|
18
27
|
> déclaré fermé est ouvert.
|
|
@@ -14,6 +14,15 @@ description: >
|
|
|
14
14
|
|
|
15
15
|
# add-service — un service que le conteneur connaît
|
|
16
16
|
|
|
17
|
+
> 🧭 **Tu es arrivé ici directement ? Charge aussi `nodefony-dev`** — il porte la conduite
|
|
18
|
+
> commune (par où commencer, comment prouver que c'est fait) et les pièges qui coûtent une heure,
|
|
19
|
+
> serveur comme front. Cette page-ci ne couvre QUE son geste.
|
|
20
|
+
>
|
|
21
|
+
> Et si une réponse te manque, elle est probablement INSTALLÉE : `rg` ne descend pas dans
|
|
22
|
+
> `node_modules`, donc 70 pages de documentation y paraissent absentes. Une commande les lit, avec
|
|
23
|
+
> la ligne exacte :
|
|
24
|
+
> `node node_modules/@nodefony/devkit/skills/nodefony-dev/scripts/docs.mjs <termes>`.
|
|
25
|
+
|
|
17
26
|
> ⚖️ **La confiance n'exclut pas le contrôle.** Un service qui compile n'est pas un service
|
|
18
27
|
> enregistré. Le seul juge est l'application en marche.
|
|
19
28
|
|
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: nodefony-browser
|
|
3
3
|
description: >
|
|
4
|
-
Ouvre un écran de ton application dans un navigateur piloté pour le VOIR et surtout le MESURER —
|
|
4
|
+
Ouvre un écran de ton application Nodefony dans un navigateur piloté pour le VOIR et surtout le MESURER —
|
|
5
5
|
contrastes et tailles réellement calculés par le moteur de rendu, audit d'accessibilité par
|
|
6
|
-
axe-core, erreurs de console, requêtes HTTP, frames WebSocket
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
un socket temps réel de bout en bout : accueil, abonnement à un canal, action, latence médiane,
|
|
13
|
-
pont API, reconnexion. À charger AVANT de conclure quoi que ce soit sur un écran.
|
|
6
|
+
axe-core, erreurs de console, requêtes HTTP, frames WebSocket, sur ta machine ou dans un
|
|
7
|
+
conteneur jetable. Porte les sondes prêtes à l'emploi, le thème clair ou sombre — un défaut
|
|
8
|
+
d'affichage n'existe souvent que dans l'un des deux —, et les pièges qui font conclure FAUX :
|
|
9
|
+
mesurer avant que l'écran soit peuplé, ou observer un bundle qui n'est plus celui du code. Sait
|
|
10
|
+
aussi piloter un socket temps réel de bout en bout. À charger AVANT de conclure quoi que ce
|
|
11
|
+
soit sur un écran.
|
|
14
12
|
Déclencheurs : "regarde l'écran", "vérifie l'affichage", "est-ce que ça s'affiche ?",
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"la page est-elle rapide ?", "temps de chargement", "responsive ?",
|
|
19
|
-
"quelles requêtes fait la page ?", "le temps réel arrive-t-il jusqu'à l'écran ?",
|
|
20
|
-
"teste le socket", "mesure la latence du websocket", "le canal pousse-t-il ?",
|
|
21
|
-
"l'application démarre-t-elle vraiment ?".
|
|
13
|
+
"lis la console", "y a-t-il des erreurs JS ?", "mesure le contraste", "capture d'écran",
|
|
14
|
+
"vérifie l'accessibilité", "audit WCAG", "en mode sombre", "la page est-elle rapide ?",
|
|
15
|
+
"quelles requêtes fait la page ?", "teste le socket".
|
|
22
16
|
---
|
|
23
17
|
|
|
24
18
|
# see-screen — voir et MESURER un écran
|
|
25
19
|
|
|
20
|
+
> 🧭 **Tu es arrivé ici directement ? Charge aussi `nodefony-dev`** — il porte la conduite
|
|
21
|
+
> commune (par où commencer, comment prouver que c'est fait) et les pièges qui coûtent une heure,
|
|
22
|
+
> serveur comme front. Cette page-ci ne couvre QUE son geste.
|
|
23
|
+
>
|
|
24
|
+
> Et si une réponse te manque, elle est probablement INSTALLÉE : `rg` ne descend pas dans
|
|
25
|
+
> `node_modules`, donc 70 pages de documentation y paraissent absentes. Une commande les lit, avec
|
|
26
|
+
> la ligne exacte :
|
|
27
|
+
> `node node_modules/@nodefony/devkit/skills/nodefony-dev/scripts/docs.mjs <termes>`.
|
|
28
|
+
|
|
26
29
|
> ⚖️ **La confiance n'exclut pas le contrôle.** Un `curl` prouve qu'une route répond ; il ne dit
|
|
27
30
|
> pas si l'écran se monte, s'alimente et ne crie pas dans la console.
|
|
28
31
|
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nodefony-dev
|
|
3
|
+
description: >
|
|
4
|
+
Conduit une tâche de développement de bout en bout dans une application Nodefony — comprendre
|
|
5
|
+
le code en place, choisir la bonne façade, générer plutôt qu'écrire à la main, retrouver la
|
|
6
|
+
référence installée qu'une recherche ordinaire ne voit pas, puis prouver que c'est fait — et se
|
|
7
|
+
charge AVANT la première modification, quelle que soit la tâche.
|
|
8
|
+
Les gestes spécialisés ont leur propre skill (ressource REST, service, canal temps réel, garde
|
|
9
|
+
de route, migration de schéma, écran vu au navigateur) ; celui-ci porte la conduite commune,
|
|
10
|
+
les pièges du serveur et du front, et dit lequel prendre.
|
|
11
|
+
Déclencheurs : "je veux ajouter une fonctionnalité", "comment on code dans ce framework",
|
|
12
|
+
"par où je commence", "où est la doc de ça", "comment ça marche ici", "avant de coder",
|
|
13
|
+
"est-ce que j'écris ça à la main", "comment vérifier que c'est bon", "mon changement
|
|
14
|
+
est-il fini", "je ne trouve rien sur ce sujet", "ce n'est pas documenté", "je touche au
|
|
15
|
+
frontend", "mon composant charge des données", "mon écran n'affiche rien".
|
|
16
|
+
metadata:
|
|
17
|
+
version: 1.1.0
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# nodefony-dev — développer dans cette application sans rien inventer
|
|
21
|
+
|
|
22
|
+
> **Maintenance** : vérité courante, jamais un journal. Éditer en place ; l'historique vit dans
|
|
23
|
+
> `git log`. Ce fichier n'a **pas** de `references/` — et c'est une décision mesurée, pas un
|
|
24
|
+
> oubli : sur 1020 transcripts d'agents lâchés dans une application générée, une page de
|
|
25
|
+
> `references/` a été ouverte **0 fois**, quand un script cité comme commande l'a été dans 80 %
|
|
26
|
+
> des cas. Ce qui doit atteindre un agent s'EXÉCUTE ou vit dans ce corps ; ce qu'on déporterait
|
|
27
|
+
> « pour alléger » n'atteindrait plus personne.
|
|
28
|
+
|
|
29
|
+
## Passer la main — TON PREMIER GESTE
|
|
30
|
+
|
|
31
|
+
🔴 **Ta tâche est dans cette table ? CHARGE ce skill MAINTENANT, avant d'écrire une ligne, avant
|
|
32
|
+
même d'ouvrir un fichier.** Ce n'est pas un conseil de lecture : c'est le premier geste de la
|
|
33
|
+
tâche. Reviens ici ensuite si tu en as encore besoin.
|
|
34
|
+
|
|
35
|
+
**Ce que coûte de ne pas le faire, mesuré au banc, six exécutions :** chaque agent qui a chargé le
|
|
36
|
+
skill de sa tâche a réussi ; **chacun de ceux qui ne l'ont pas chargé a échoué** — l'un en
|
|
37
|
+
cherchant la base de l'application au mauvais endroit puis en l'effaçant, l'autre en écrivant une
|
|
38
|
+
migration qu'il n'a jamais appliquée. Aucun ne manquait d'information : la table était sous leurs
|
|
39
|
+
yeux. Ils ont simplement continué sans elle.
|
|
40
|
+
|
|
41
|
+
Ces skills sont installés avec le framework et se chargent par leur nom. Chacun porte les pièges
|
|
42
|
+
de son geste, et ceux-là ne se devinent pas — ils se paient.
|
|
43
|
+
|
|
44
|
+
| Ce que tu t'apprêtes à faire | Le skill |
|
|
45
|
+
| -------------------------------------------------------------------- | ------------------------------- |
|
|
46
|
+
| Une ressource : table, validation, service, REST et WebSocket | `nodefony-add-crud` |
|
|
47
|
+
| Une logique métier réutilisable, hors de tout controller | `nodefony-add-service` |
|
|
48
|
+
| Un flux temps réel, un canal, un abonnement client | `nodefony-add-realtime-channel` |
|
|
49
|
+
| Réserver une route, un rôle, une zone, ouvrir à un partenaire | `nodefony-protect-route` |
|
|
50
|
+
| Changer une entité déjà en base, ou déployer un schéma changé | `nodefony-migrate-schema` |
|
|
51
|
+
| Conclure quoi que ce soit d'un ÉCRAN — affichage, contraste, console | `nodefony-browser` |
|
|
52
|
+
|
|
53
|
+
Aucune ligne ne correspond ? Alors seulement, continue ici. Et si ta tâche est EXACTEMENT celle
|
|
54
|
+
d'un spécialiste, va droit à lui : il n'y a pas à passer par cette page d'abord.
|
|
55
|
+
|
|
56
|
+
`ls .agents/skills/` liste ceux que TON projet a reçus ; `npx nodefony ai:sync` les remet à jour
|
|
57
|
+
après une montée de version. Ce sont des **pointeurs** : le contenu vit dans `node_modules` et
|
|
58
|
+
suit la version installée — les éditer ne servirait à rien.
|
|
59
|
+
|
|
60
|
+
## 1. La règle qui gouverne tout
|
|
61
|
+
|
|
62
|
+
**N'invente jamais du code Nodefony : génère-le, imite-le, vérifie-le.**
|
|
63
|
+
|
|
64
|
+
Ton `AGENTS.md` porte les trois actes et les tables qui vont avec — les générateurs, les
|
|
65
|
+
vérités du framework, les gates. **Ce skill ne les recopie pas** : une règle écrite à deux
|
|
66
|
+
endroits diverge au premier changement, et c'est alors la copie qu'on lit. Il porte ce qui n'y
|
|
67
|
+
tient pas : la **conduite** d'une tâche, les pièges qui coûtent une heure, et l'outil qui répond
|
|
68
|
+
à « où est-ce documenté ? ».
|
|
69
|
+
|
|
70
|
+
Le réflexe, avant d'écrire le moindre fichier : **un générateur le produit-il ?**
|
|
71
|
+
`npx nodefony create --help` liste ceux de TA version — la liste s'allonge, ta mémoire non.
|
|
72
|
+
|
|
73
|
+
## 2. Trouver la référence — ce que `rg` ne peut pas voir
|
|
74
|
+
|
|
75
|
+
C'est le trou le plus coûteux de ce framework, et il ne ressemble pas à un trou : **la
|
|
76
|
+
documentation est installée, complète, et invisible**. `rg "session"` lancé à la racine ne
|
|
77
|
+
descend pas dans `node_modules` (git l'ignore, `rg` le suit). Le sujet paraît absent alors qu'il
|
|
78
|
+
occupe quinze pages — mesuré sur une application générée : **70 pages, plus de 38 000 lignes**.
|
|
79
|
+
|
|
80
|
+
Conclure « ce n'est pas documenté » et réécrire à la main est l'erreur que ce script existe pour
|
|
81
|
+
empêcher :
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
D=node_modules/@nodefony/devkit/skills/nodefony-dev/scripts/docs.mjs
|
|
85
|
+
|
|
86
|
+
node $D session cookie # les pages qui répondent — chemin, LIGNE, extrait
|
|
87
|
+
node $D --list # tout ce qui est installé, par module
|
|
88
|
+
node $D --open firewall # le chemin d'une page, pour l'ouvrir
|
|
89
|
+
node $D upload --json # pour rechaîner
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Il ne stocke aucune documentation : il lit celle de TES paquets à l'exécution, et rend le chemin
|
|
93
|
+
**et la ligne**. Tu ouvres à l'endroit exact au lieu de relire une page entière. Classement par
|
|
94
|
+
titre, sujet, étiquettes puis corps — une ligne qui porte TOUS tes termes passe devant deux
|
|
95
|
+
lignes qui en portent un chacune ; les accents sont ignorés.
|
|
96
|
+
|
|
97
|
+
**Ses codes de sortie disent quoi faire**, et l'un d'eux compte plus que les autres :
|
|
98
|
+
|
|
99
|
+
| Code | Ce qu'il veut dire | Le geste |
|
|
100
|
+
| ---: | ----------------------- | ------------------------------------------------------------- |
|
|
101
|
+
| 0 | trouvé | ouvrir le fichier à la ligne rendue |
|
|
102
|
+
| 1 | rien sur ces termes | un seul mot, ou `--list` pour voir les sujets couverts |
|
|
103
|
+
| 78 | **rien n'est installé** | `npm install` — ce n'est PAS « le sujet n'est pas documenté » |
|
|
104
|
+
| 64 | drapeau inconnu | `--help` |
|
|
105
|
+
|
|
106
|
+
> 🔴 **`78` n'est pas une panne, c'est une information.** Un projet dont les dépendances ne sont
|
|
107
|
+
> pas installées n'a aucune documentation à lire. Le DIRE ; ne jamais réécrire de mémoire ce
|
|
108
|
+
> qu'on n'a pas pu lire.
|
|
109
|
+
|
|
110
|
+
Deux autres voies existent quand l'application **tourne** : l'outil MCP `nodefony_docs` (cherche
|
|
111
|
+
dans la doc chargée) et `nodefony_symbols` (rend la SIGNATURE réelle d'un symbole, que ce script
|
|
112
|
+
ne porte pas). Elles supposent un serveur démarré et la porte câblée (`npx nodefony ai:mcp`) ;
|
|
113
|
+
`docs.mjs`, lui, répond toujours.
|
|
114
|
+
|
|
115
|
+
## 3. Conduire une tâche — la séquence, et ses points d'arrêt
|
|
116
|
+
|
|
117
|
+
1. **Demande à l'application, ne déduis pas du code.** `npx nodefony inspect routes`,
|
|
118
|
+
`inspect services`, `inspect config` rendent l'état RÉEL — routes montées, services résolus,
|
|
119
|
+
valeur effective **et sa provenance**. Une route lue dans un fichier peut n'être montée nulle
|
|
120
|
+
part ; l'inverse aussi.
|
|
121
|
+
**Un argument RESTREINT la réponse** — `inspect routes auth` ne rend que les routes dont le
|
|
122
|
+
chemin, le nom, le contrôleur, l'action, le module ou les méthodes portent `auth` ;
|
|
123
|
+
`inspect schema http` fait de même sur les réglages d'un module. Ne tronque JAMAIS une sortie
|
|
124
|
+
d'inspection (`| head`) pour la faire tenir : une application en sert facilement plusieurs
|
|
125
|
+
centaines, et ce qu'on cherche est presque toujours dans la partie coupée — c'est ainsi qu'on
|
|
126
|
+
conclut « le framework ne fournit pas ça » et qu'on le réécrit à la main.
|
|
127
|
+
2. **Cherche la référence** (§2) avant de choisir une façade. Le framework en a presque toujours
|
|
128
|
+
une, et la contourner compile — c'est tout le piège.
|
|
129
|
+
3. **Génère.** Si un générateur couvre le besoin, lance-le et **imite sa sortie** pour le reste.
|
|
130
|
+
`--dry-run` montre le plan et les diffs sans rien écrire ; un refus n'écrit jamais rien.
|
|
131
|
+
4. **Édite le moins possible**, et regroupe : toutes les modifications serveur d'une même
|
|
132
|
+
fonctionnalité, PUIS un seul cycle de reconstruction. Le frontend passe en HMR, zéro
|
|
133
|
+
redémarrage.
|
|
134
|
+
5. **Prouve.** `npm run verify` — une seule commande : types, style, tests, câblage, dans cet
|
|
135
|
+
ordre. Elle s'arrête au premier rouge, et **ce rouge est ta tâche suivante**.
|
|
136
|
+
|
|
137
|
+
**Le point d'arrêt qu'on rate** : `npm test` seul ne prouve pas que ça compile — vitest
|
|
138
|
+
n'inspecte aucun type. Une application peut être verte et ne pas compiler.
|
|
139
|
+
|
|
140
|
+
## 4. Les pièges du serveur
|
|
141
|
+
|
|
142
|
+
Chacun a déjà coûté au moins une heure à quelqu'un. Les quatre premiers sont les plus fréquents.
|
|
143
|
+
|
|
144
|
+
- **Ta route répond 404 alors qu'elle existe dans les sources.** Le runtime charge `dist/`, pas
|
|
145
|
+
le source : `npm run build`. C'est la cause n°1.
|
|
146
|
+
- **Une classe que rien ne déclare compile, passe ses tests, et casse au démarrage suivant** —
|
|
147
|
+
entité hors `@entities([…])`, controller hors `@controllers([…])`. Table jamais créée, route
|
|
148
|
+
en 404. C'est le mode d'échec de la COPIE : on recopie le voisin au lieu d'appeler le
|
|
149
|
+
générateur, qui, lui, déclare. `npx nodefony doctor` la NOMME.
|
|
150
|
+
- **Une clé de configuration mal orthographiée est retirée en silence.** `satisfies` sur le
|
|
151
|
+
fragment n'est pas décoratif : sans lui, la faute compile, puis la validation écarte la clé et
|
|
152
|
+
le module démarre sur son défaut. Personne ne le voit.
|
|
153
|
+
- **Tu lis une liste sans la BORNER.** Un `find` sans limite matérialise la table entière —
|
|
154
|
+
indolore sur les quelques lignes du poste de développement, fatal sur les dizaines de milliers
|
|
155
|
+
de la production. Le service d'une entité hérite `findPage({ limit: 25 })`.
|
|
156
|
+
|
|
157
|
+
### Ce qui tue le processus, pas la requête
|
|
158
|
+
|
|
159
|
+
- 🔴 **Une promesse lancée sans `await` porte TOUJOURS un `.catch()`.** Audit, courriel,
|
|
160
|
+
notification, nettoyage différé : un rejet non capté ne casse pas la requête, il tue le
|
|
161
|
+
**processus entier** — donc toutes les requêtes en vol, pas seulement la tienne.
|
|
162
|
+
- 🔴 **Un handler ne bloque jamais la boucle d'événements.** Aucune API `*Sync`
|
|
163
|
+
(`readFileSync`, `pbkdf2Sync`, `zlib`, `child_process`), aucun `JSON.parse` sur un corps non
|
|
164
|
+
borné, aucune expression régulière à quantificateurs imbriqués sur une entrée utilisateur.
|
|
165
|
+
Au-delà d'une milliseconde de calcul, passe par `worker_threads` : un seul handler lourd
|
|
166
|
+
bloque **tous** les clients, pas seulement celui qui l'a déclenché.
|
|
167
|
+
- **Un `PATCH` au corps vide se refuse en `400`.** Le laisser passer produit un `updateOne({})`,
|
|
168
|
+
qui finit en `500 « No values to set »` — une erreur serveur pour une faute de client.
|
|
169
|
+
|
|
170
|
+
### Quand ça ne va pas, et que le message ne suffit pas
|
|
171
|
+
|
|
172
|
+
- **Un test vert seul et rouge en suite accuse une RESSOURCE PARTAGÉE**, pas ton code : base ou
|
|
173
|
+
index réutilisé, port, store jamais purgé, assertion `count === N` qui suppose une table
|
|
174
|
+
vierge. Lance deux fichiers ENSEMBLE pour isoler la paire, puis cloisonne. **Ne sérialise
|
|
175
|
+
jamais la suite** pour faire passer le rouge : tu masques la cause et tu paies la lenteur à
|
|
176
|
+
chaque exécution.
|
|
177
|
+
- **Une suite lancée contre un serveur en `production` reçoit `404` partout** : les modules
|
|
178
|
+
`policy:"dev"` n'y sont pas. `NF_WITH_DEV_MODULES=1` déroge pour 30 minutes
|
|
179
|
+
(`NF_WITH_DEV_MODULES_TTL_MIN`, 4 h au plus), et le `CRITIC « arrêt automatique … dérogation »`
|
|
180
|
+
du journal est cette garde qui se referme — pas une panne.
|
|
181
|
+
- **Ton application a démarré AMPUTÉE et tout a l'air sain** — base injoignable, module écarté
|
|
182
|
+
par sa politique. Seul `npx nodefony doctor` le dit, en relisant `var/last-boot.json`.
|
|
183
|
+
⚠️ Ce bilan a un ÂGE : il décrit le **dernier démarrage**, et une commande console (`inspect`,
|
|
184
|
+
une commande de module) ne l'écrase pas. C'est voulu — lis la date avant d'en conclure.
|
|
185
|
+
- **L'application ne démarre plus et le superviseur avale la sortie** :
|
|
186
|
+
`NF_DEV_CHILD=1 npx nodefony development` lance l'enfant seul et montre le crash brut.
|
|
187
|
+
|
|
188
|
+
## 5. Les pièges du front
|
|
189
|
+
|
|
190
|
+
Ne concerne qu'une application qui a un frontend. Sauf mention, **vaut pour les quatre moteurs**
|
|
191
|
+
(React, Vue, Angular, Svelte) : le framework ne t'en impose aucun.
|
|
192
|
+
|
|
193
|
+
### Ce qui fuit, et ce qui s'injecte
|
|
194
|
+
|
|
195
|
+
- 🔴 **Toute donnée non maîtrisée se rend en nœud TEXTE.** Jamais `dangerouslySetInnerHTML`
|
|
196
|
+
(React), `v-html` (Vue), `[innerHTML]` (Angular), `{@html}` (Svelte). Un Markdown se rend sans
|
|
197
|
+
HTML brut.
|
|
198
|
+
- 🔴 **L'identité est un cookie `HttpOnly` que le navigateur joint seul.** Aucun jeton en
|
|
199
|
+
`localStorage` ou `sessionStorage`, aucun en-tête `Authorization` écrit à la main. Un `401`
|
|
200
|
+
est un ÉTAT (« pas connecté »), pas une erreur à journaliser.
|
|
201
|
+
- 🔴 **Le bundle front n'importe jamais un module serveur** — `@nodefony/http`,
|
|
202
|
+
`@nodefony/security`, une entité ORM, `nodefony.config`, `.env`. Un type serveur passe par
|
|
203
|
+
`import type` ou un miroir. Le test qui tranche : **si l'import tire un `node:*`, arrête-toi**
|
|
204
|
+
— ce bundle est public.
|
|
205
|
+
- **Rien de secret ne part côté client.** Toute clé `VITE_*` est lue par le navigateur ; un
|
|
206
|
+
`console.*` de données committé est une fuite. Le front AFFICHE ce qu'il reçoit — la rédaction
|
|
207
|
+
des secrets est un travail de serveur.
|
|
208
|
+
|
|
209
|
+
### Charger des données sans casser l'écran
|
|
210
|
+
|
|
211
|
+
- **Un écran qui charge a quatre états EXCLUSIFS**, dans cet ordre de priorité : erreur (avec un
|
|
212
|
+
« réessayer »), chargement (un squelette qui épouse la page), vide (qui dit POURQUOI), données.
|
|
213
|
+
Un seul visible à la fois.
|
|
214
|
+
- **Tout chargement porte un jeton de génération** : une réponse arrivée après démontage, ou
|
|
215
|
+
après un changement de paramètre, est IGNORÉE — sinon un écran affiche les données d'un autre.
|
|
216
|
+
`loading` vaut `true` dès le montage, jamais après. Le framework ne fournit pas de hook de
|
|
217
|
+
ressource : c'est à écrire, dans les quatre moteurs.
|
|
218
|
+
- **Au vrai changement de compte** (l'identifiant passe d'une valeur à une AUTRE), force
|
|
219
|
+
`disconnect()` puis `connect()` sur la socket partagée et purge les caches propres à
|
|
220
|
+
l'utilisateur. Jamais au démarrage ni au rechargement : tu couperais les requêtes en vol.
|
|
221
|
+
|
|
222
|
+
### Un écran qui se met à jour tout seul
|
|
223
|
+
|
|
224
|
+
- **Un widget temps réel est invisible tant qu'il ne se passe rien.** Format par paliers (jamais
|
|
225
|
+
une valeur qui saute de millisecondes à secondes), `font-variant-numeric: tabular-nums` sur
|
|
226
|
+
tout nombre qui change, aucune animation rejouée à chaque tick, `prefers-reduced-motion`
|
|
227
|
+
respecté, et un contrôle pause/fréquence dès que ça bouge seul plus de 5 s (WCAG 2.2.2).
|
|
228
|
+
**Le test** : fixe l'écran 30 secondes — rien ne doit bouger sans cause.
|
|
229
|
+
- **N'anime que `transform` et `opacity`** ; `contain: content` sur chaque widget vivant,
|
|
230
|
+
`content-visibility: auto` sur les longues listes.
|
|
231
|
+
- **Accessibilité, le minimum qui se vérifie à l'œil** : un seul `<h1>` par page, `aria-label`
|
|
232
|
+
sur tout bouton-icône, `aria-expanded` sur tout bascule, `aria-live` sur les zones qui changent
|
|
233
|
+
seules, `role="img"` + `aria-label` sur un graphe SVG, jamais une information portée par la
|
|
234
|
+
**couleur seule**, `rel="noopener noreferrer"` sur les liens externes.
|
|
235
|
+
|
|
236
|
+
### Le piège qui fait croire à un bug de code
|
|
237
|
+
|
|
238
|
+
- **Vite affirme qu'un export n'existe pas** (`does not provide an export named …`) alors qu'il
|
|
239
|
+
est bien dans le source — typiquement après un nouveau sous-chemin `nodefony/*`, une dépendance
|
|
240
|
+
ajoutée, ou un `git pull`. C'est son cache : `rm -rf node_modules/.vite`, puis relance. Ne
|
|
241
|
+
purge pas sans raison, ça coûte 5 à 20 s de ré-optimisation.
|
|
242
|
+
|
|
243
|
+
## 6. Avant de dire « fait »
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
npm run verify # types + style + tests + câblage
|
|
247
|
+
npm run test:e2e # boot réel + HTTP/WS — le gate LENT, hors `verify`
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Puis, en une phrase : **nomme ce que tu n'as PAS lancé.** Un vert ne couvre que le diff qui l'a
|
|
251
|
+
produit, et un banc sauté faute de son décor compte comme vert. Dire « e2e non lancé » coûte
|
|
252
|
+
cinq mots ; le taire coûte la confiance dans tout le reste.
|
|
253
|
+
|
|
254
|
+
Quatre règles de plus, chacune payée par une conclusion fausse qu'on a crue. Elles ne parlent
|
|
255
|
+
pas de ce framework en particulier — elles parlent de la façon dont une preuve se fabrique.
|
|
256
|
+
|
|
257
|
+
- 🔴 **Ta preuve porte sur l'artefact qu'on REÇOIT, pas sur ce que tu viens d'écrire.** Le
|
|
258
|
+
runtime charge `dist/`, une image embarque ce que le `Dockerfile` a copié, un paquet publié
|
|
259
|
+
contient ce que `files` laisse passer. Et avant de mesurer, vérifie que la transformation a
|
|
260
|
+
bien EU LIEU (date, empreinte) : dans une chaîne `a && b && c`, un maillon qui échoue laisse
|
|
261
|
+
mesurer l'ancienne version — et « prouver » qu'un correctif ne change rien.
|
|
262
|
+
- 🔴 **Un test que tu n'as jamais vu ROUGE ne prouve rien.** Écris-le, puis casse exprès ce
|
|
263
|
+
qu'il garde : retire le correctif, débranche le câblage. S'il reste vert, il ne mesure pas ce
|
|
264
|
+
que tu crois. Remets, et alors seulement crois-le. Un test écrit face au code déjà corrigé est
|
|
265
|
+
complaisant par construction.
|
|
266
|
+
- **Un décor SALE fabrique des verdicts faux** : un serveur resté ouvert sur le port, une base
|
|
267
|
+
jamais purgée, une variable d'environnement absente. Avant d'accuser ton code, qualifie le
|
|
268
|
+
rouge sur un décor NEUF — sinon tu corriges un problème qui n'existe pas, et tu laisses
|
|
269
|
+
intact celui qui existe.
|
|
270
|
+
- **Suspecte ton instrument avant de suspecter le code.** Une commande qui rend « 0 résultat »,
|
|
271
|
+
un compteur à zéro, un journal vide : demande-toi d'abord si l'outil regarde au bon endroit.
|
|
272
|
+
Une sortie tronquée, un filtre trop étroit, un chemin qui n'existe plus ne s'annoncent jamais
|
|
273
|
+
— ils rendent un silence qui ressemble à une réponse.
|