@nodefony/devkit 10.0.0-beta.3 → 10.0.0-beta.5
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/README.md +146 -4
- package/dist/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.155.0}/helpers/esm/decorate.js +1 -2
- package/dist/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.155.0}/helpers/esm/decorateParam.js +1 -2
- package/dist/index.js +24 -11
- package/dist/nodefony/config/config.js +16 -137
- package/dist/nodefony/config/defineModuleConfig.js +1 -2
- package/dist/nodefony/controllers/DevkitController.js +7 -14
- package/dist/nodefony/controllers/McpController.js +25 -226
- package/dist/nodefony/controllers/ProfileSessionController.js +47 -0
- package/dist/nodefony/mcp/observe.js +235 -0
- package/dist/nodefony/mcp/profileReport.js +242 -0
- package/dist/nodefony/mcp/profileRoute.js +521 -0
- package/dist/nodefony/mcp/shotClient.js +84 -0
- package/dist/nodefony/mcp/shutdown.js +44 -0
- package/dist/nodefony/mcp/tools.js +696 -0
- package/dist/nodefony/service/DevkitService.js +93 -29
- package/dist/nodefony/src/errors/DevkitError.js +1 -2
- package/dist/nodefony/src/profileSession.js +14 -0
- package/dist/types/index.d.ts +15 -1
- package/dist/types/nodefony/config/config.d.ts +1 -1
- package/dist/types/nodefony/controllers/McpController.d.ts +11 -26
- package/dist/types/nodefony/controllers/ProfileSessionController.d.ts +31 -0
- package/dist/types/nodefony/interfaces/IDevkitService.d.ts +22 -1
- package/dist/types/nodefony/mcp/observe.d.ts +83 -0
- package/dist/types/nodefony/mcp/profileReport.d.ts +138 -0
- package/dist/types/nodefony/mcp/profileRoute.d.ts +87 -0
- package/dist/types/nodefony/mcp/shotClient.d.ts +53 -0
- package/dist/types/nodefony/mcp/shutdown.d.ts +25 -0
- package/dist/types/nodefony/mcp/tools.d.ts +109 -0
- package/dist/types/nodefony/service/DevkitService.d.ts +41 -4
- package/dist/types/nodefony/src/profileSession.d.ts +12 -0
- package/docs/index.md +160 -11
- package/package.json +16 -11
- package/skills/nodefony-add-crud/SKILL.md +10 -1
- package/skills/nodefony-add-service/SKILL.md +3 -3
- package/skills/nodefony-authentication/SKILL.md +5 -5
- package/skills/nodefony-browser/SKILL.md +20 -0
- package/skills/nodefony-browser/references/socket.md +13 -4
- package/skills/nodefony-browser/references/sondes.md +13 -1
- package/skills/nodefony-browser/scripts/inspect.mjs +55 -8
- package/skills/nodefony-browser/scripts/lib/probes.mjs +53 -0
- package/skills/nodefony-browser/scripts/socket.mjs +70 -4
- package/skills/nodefony-browser/scripts/watch.mjs +101 -0
- package/skills/nodefony-dev/SKILL.md +31 -1
- package/skills/nodefony-dev/scripts/docs.mjs +3 -3
- package/skills/nodefony-devops/SKILL.md +85 -64
- package/skills/nodefony-devops/references/dimensionnement.md +122 -0
- package/skills/nodefony-devops/references/frontal.md +277 -47
- package/skills/nodefony-devops/references/kubernetes.md +41 -14
- package/skills/nodefony-devops/references/secrets.md +13 -2
- package/skills/nodefony-devops/references/variables.md +14 -12
- package/skills/nodefony-protect-route/SKILL.md +6 -4
- package/skills/nodefony-security-review/scripts/review-diff.mjs +4 -4
- package/skills/nodefony-troubleshoot/SKILL.md +86 -12
- package/dist/_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/decorateMetadata.js +0 -6
|
@@ -515,7 +515,7 @@ export function readZones(src) {
|
|
|
515
515
|
const authenticators = auth
|
|
516
516
|
? [...auth[1].matchAll(/["']([^"']+)["']/gu)].map((a) => a[1])
|
|
517
517
|
: [];
|
|
518
|
-
let regex
|
|
518
|
+
let regex;
|
|
519
519
|
try {
|
|
520
520
|
regex = new RegExp(m[2].replace(/\\\\/gu, "\\"), "u");
|
|
521
521
|
} catch {
|
|
@@ -544,7 +544,7 @@ export function readZones(src) {
|
|
|
544
544
|
export function appZones(root) {
|
|
545
545
|
const files = [];
|
|
546
546
|
const walk = (dir) => {
|
|
547
|
-
let entries
|
|
547
|
+
let entries;
|
|
548
548
|
try {
|
|
549
549
|
entries = readdirSync(dir, { withFileTypes: true });
|
|
550
550
|
} catch {
|
|
@@ -673,8 +673,8 @@ export function controllerRoutes(lines) {
|
|
|
673
673
|
const group = decoratorGroup(lines, i);
|
|
674
674
|
if (seen.has(group.to)) continue;
|
|
675
675
|
seen.add(group.to);
|
|
676
|
-
let routePath
|
|
677
|
-
let methods
|
|
676
|
+
let routePath;
|
|
677
|
+
let methods;
|
|
678
678
|
if (verbDeco) {
|
|
679
679
|
routePath =
|
|
680
680
|
new RegExp(
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: nodefony-troubleshoot
|
|
3
3
|
description: >
|
|
4
|
-
Dépanne une application Nodefony en partant du SYMPTÔME constaté — démarrage qui échoue,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
`nodefony-dev`.
|
|
4
|
+
Dépanne une application Nodefony en partant du SYMPTÔME constaté — démarrage qui échoue, route
|
|
5
|
+
en 404, refus 401 ou 403 inattendu, erreur au journal, colonne absente, tests rouges d'un coup,
|
|
6
|
+
page lente — et donne pour chacun le premier geste, la commande qui le constate et le skill qui
|
|
7
|
+
porte le détail. Extrait les erreurs du journal par un script ; mesure une route par l'outil MCP
|
|
8
|
+
`nodefony_profile_route` (il tire lui-même les requêtes), le trafic qu'on génère par
|
|
9
|
+
`nodefony_observe`. À charger DÈS qu'une chose qui marchait ne marche plus, AVANT de lire les
|
|
10
|
+
sources ou de contourner la panne. Coder une fonctionnalité → `nodefony-dev`.
|
|
11
11
|
Déclencheurs : "l'application ne démarre plus", "le serveur plante au démarrage", "ma route
|
|
12
|
-
répond 404", "ça marchait hier", "
|
|
13
|
-
"
|
|
14
|
-
"
|
|
12
|
+
répond 404", "ça marchait hier", "dépanner", "erreur dans les logs", "tous mes tests sont
|
|
13
|
+
rouges", "cette page est lente", "trop de requêtes SQL", "problème de N+1", "mesure cette route",
|
|
14
|
+
"est-ce plus rapide après ma modification", "erreur 500 intermittente", "EADDRINUSE",
|
|
15
|
+
"ECONNREFUSED".
|
|
15
16
|
metadata:
|
|
16
|
-
version: 1.
|
|
17
|
+
version: 1.1.0
|
|
17
18
|
---
|
|
18
19
|
|
|
19
20
|
# nodefony-troubleshoot — du symptôme au geste, sans contourner
|
|
@@ -60,6 +61,7 @@ cause t'échappe, dis-le, avec ce que tu as constaté.
|
|
|
60
61
|
| Une erreur dans le journal | le script du §3 | la piste qu'il donne, sinon le message lui-même |
|
|
61
62
|
| « colonne inexistante », « no such table », migrations à appliquer | `npx nodefony doctor --live` | `nodefony-migrate-schema` |
|
|
62
63
|
| Des dizaines de tests d'intégration rouges d'un coup (`ECONNREFUSED`) | `npx nodefony status` | ils FRAPPENT un serveur, ils ne le lancent pas : il est éteint. En e2e, laisse la commande gérer le cycle |
|
|
64
|
+
| Une page est lente, trop de requêtes SQL, des `500` par intermittence | l'outil MCP `nodefony_profile_route { "path": "/la/page" }` | §5 : le rapport nomme la route, la cause et le geste |
|
|
63
65
|
| `nodefony <commande>` échoue là où `npm run dev` réussit | `npm ls nodefony` | deux copies du framework dans le processus (§4) |
|
|
64
66
|
|
|
65
67
|
**Lis toute la réponse d'une commande de diagnostic.** Ne la tronque jamais (`| head`, une
|
|
@@ -141,7 +143,79 @@ Chacune a déjà coûté au moins une heure à quelqu'un.
|
|
|
141
143
|
anonyme et une route authentifiée AVANT d'accuser TLS ou le pare-feu ; passe le stockage sur
|
|
142
144
|
redis pour la charge.
|
|
143
145
|
|
|
144
|
-
## 5.
|
|
146
|
+
## 5. Mesurer l'application qui tourne — `nodefony_profile_route` et `nodefony_observe`
|
|
147
|
+
|
|
148
|
+
Le profileur de développement mesure chaque requête : temps de chaque phase, chaque requête SQL,
|
|
149
|
+
décision du pare-feu. Deux outils MCP te rendent ces mesures. C'est la seule façon de SAVOIR
|
|
150
|
+
qu'une page est lente ou qu'elle interroge la base dans une boucle — ni le code ni les tests ne le
|
|
151
|
+
montrent. **Mesure avant d'écrire un script de banc** : l'outil le fait déjà, et mieux.
|
|
152
|
+
|
|
153
|
+
| Tu veux… | L'outil | Qui envoie les requêtes |
|
|
154
|
+
| ---------------------------------------------------------------- | ------------------------ | --------------------------------------- |
|
|
155
|
+
| mesurer UNE page, avant/après une modification | `nodefony_profile_route` | l'outil lui-même, N fois, sur un chemin |
|
|
156
|
+
| voir ce que fait le trafic que TU génères (tests, navigation, …) | `nodefony_observe` | toi, pendant une fenêtre de secondes |
|
|
157
|
+
|
|
158
|
+
**Le protocole — mesurer, corriger, re-mesurer :**
|
|
159
|
+
|
|
160
|
+
1. **Une page** : `nodefony_profile_route { "path": "/orders?page=2" }` — un CHEMIN de
|
|
161
|
+
l'application, jamais une URL. `count` (défaut 50, max 200), `concurrency` (défaut 4, max 8),
|
|
162
|
+
`warmup` (défaut 3 : requêtes tirées AVANT et hors mesures — la première compile la route et
|
|
163
|
+
ouvre la connexion à la base). GET (défaut) ou HEAD seulement.
|
|
164
|
+
**Un trafic** : `nodefony_observe { "durationSec": 10 }` (1 à 50 s), et PENDANT la fenêtre,
|
|
165
|
+
sollicite le code — l'outil n'envoie RIEN ; sans trafic, son verdict est « rien à juger ».
|
|
166
|
+
`"route"` restreint à une route, par son NOM (`nodefony_inspect` sujet `routes`).
|
|
167
|
+
2. Lis le rapport (ci-dessous), corrige la cause nommée.
|
|
168
|
+
3. **Rappelle l'outil avec les MÊMES arguments** et compare le bloc `Données (JSON…)` des deux
|
|
169
|
+
appels : un correctif qu'on n'a pas vu changer le chiffre est une hypothèse. Exemple réel, un
|
|
170
|
+
N+1 corrigé par `$in` : 18 requêtes SQL par page → 3, p50 1,2 ms → 0,7 ms.
|
|
171
|
+
|
|
172
|
+
**Au nom de qui — une page protégée vue sans compte ne mesure que des refus.**
|
|
173
|
+
`nodefony_profile_route` joue par défaut le **propriétaire du jeton MCP** si ce jeton porte le
|
|
174
|
+
scope `admin:write` : il ouvre une vraie session à son nom (tous ses rôles), tire avec, puis la
|
|
175
|
+
détruit — l'audit l'écrit (`login.success`, raison `devkit`). `"as": "<identifiant>"` joue un autre
|
|
176
|
+
compte, dont les rôles doivent être inclus dans ceux du propriétaire (jamais de montée en droits).
|
|
177
|
+
`"anonymous": true` force l'anonyme. Sans `admin:write`, l'outil joue l'anonyme et le rapport dit
|
|
178
|
+
la commande : `npx nodefony security:mcp:token --scope "admin:read admin:write" --write` — puis
|
|
179
|
+
relance l'agent, qui lit son jeton au démarrage.
|
|
180
|
+
|
|
181
|
+
**Lire le rapport, dans l'ordre où il s'écrit :**
|
|
182
|
+
|
|
183
|
+
| Ligne | Ce qu'elle dit | Le geste |
|
|
184
|
+
| -------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
185
|
+
| `Verdict : … INCOMPLÈTE` + `⚠️` | les chiffres ne portent pas sur tout — la cause suit, AVANT tout chiffre | lever la cause nommée, rappeler l'outil |
|
|
186
|
+
| `⚠️ … REFUSÉE(S) (401×…, 403×…)` | la page est protégée : ces requêtes ne mesurent rien (verdict « rien à juger ») | anonyme → le jeton `admin:write` ; compte → un compte qui a le rôle (`as`), ou la zone n'accepte pas la session |
|
|
187
|
+
| `⚠️ … REDIRIGÉE(S) vers /login` | la page renvoie vers la connexion : on mesure la redirection, pas la page | jouer un compte, comme ci-dessus |
|
|
188
|
+
| `Tir :` · `Joué en tant que :` | ce qui a été envoyé, la chauffe, l'identité réellement jouée | vérifier que c'est bien la mesure voulue |
|
|
189
|
+
| `N+1 — route … ×N dans une requête` | la même requête SQL répétée N fois dans UNE requête HTTP : une boucle sur la base | charger d'un coup : `relations` du dépôt, ou `$in` sur les identifiants |
|
|
190
|
+
| `Erreurs — route …` + `Journal …` | les `5xx` et les lignes WARNING/ERROR de leur journal, par `requestId` | corriger d'après le message ; `nodefony_admin_call` syslog `logs` pour la suite du journal |
|
|
191
|
+
| `Lente — route … p95 …` | p95 ≥ 500 ms, avec ce qui coûte par requête | `action.self` domine → le code de l'action ou d'un service ; `SQL (cumul)` → les requêtes ; `render` → la vue |
|
|
192
|
+
| `Boucle d'événements bloquée` | un traitement SYNCHRONE a gelé le process ≥ 100 ms : toutes les routes ont attendu | chercher la boucle lourde, l'API `*Sync`, le gros `JSON.parse` ; juste après un démarrage, rappeler plus tard |
|
|
193
|
+
| `Refus (hors percentiles)` (`observe`) | des `401`/`403` dans le trafic observé : ces requêtes ne mesurent rien | appeler avec une session ou un jeton, pas conclure sur ces durées |
|
|
194
|
+
|
|
195
|
+
**Pièges :**
|
|
196
|
+
|
|
197
|
+
- **Ne modifie AUCUN fichier pendant la mesure** : le serveur de développement redémarre, l'outil
|
|
198
|
+
rend un rapport partiel marqué « interrompu ». Rappelle-le une fois le serveur relancé.
|
|
199
|
+
- **Les requêtes de `nodefony_profile_route` sont de VRAIES requêtes** : une page qui écrit en GET
|
|
200
|
+
(compteur, session créée pour chaque visiteur anonyme) écrit N fois. Le rapport le montre — c'est
|
|
201
|
+
souvent une découverte en soi.
|
|
202
|
+
- **Les zones à jeton (`jwt`, `external-jwt`) ne sont pas jouées** : seule la session l'est ; leurs
|
|
203
|
+
requêtes rendent `401`, et le rapport le dit.
|
|
204
|
+
- **Le journal d'une `5xx` n'est lu que par un appelant authentifié** (scope `admin:read`). Sans
|
|
205
|
+
jeton, le rapport le dit et nomme le geste.
|
|
206
|
+
- **`nodefony_observe` écarte l'outillage (`/nodefony/…`)** — console, API d'administration, porte
|
|
207
|
+
MCP ; `"includeTooling": true` le compte. `nodefony_profile_route` mesure le chemin qu'on lui
|
|
208
|
+
donne, quel qu'il soit.
|
|
209
|
+
- **Les valeurs SQL sont masquées** (`?`) : le rapport montre la FORME d'une requête, jamais une
|
|
210
|
+
donnée.
|
|
211
|
+
- **« boucle d'événements : non mesurée »** : le tir a duré moins de cinq périodes de la sonde ;
|
|
212
|
+
augmente `count` pour la lire.
|
|
213
|
+
- **Abandonner l'appel** n'arrête pas toujours l'outil côté serveur : selon le client, il va au bout
|
|
214
|
+
de son tir (45 s au plus) ou de sa fenêtre.
|
|
215
|
+
- Les deux outils n'existent qu'en **développement** (`@nodefony/devkit`) ; ailleurs, ils répondent
|
|
216
|
+
qu'il n'y a aucun profileur.
|
|
217
|
+
|
|
218
|
+
## 6. Avant de dire « réparé »
|
|
145
219
|
|
|
146
220
|
1. **Rejoue le symptôme d'origine** — la même requête, la même commande — et constate qu'il a
|
|
147
221
|
disparu. Un correctif qu'on n'a pas vu agir sur le symptôme est une hypothèse.
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
//#region \0@oxc-project+runtime@0.153.0/helpers/esm/decorateMetadata.js
|
|
2
|
-
function __decorateMetadata(k, v) {
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
4
|
-
}
|
|
5
|
-
//#endregion
|
|
6
|
-
export { __decorateMetadata as default };
|