@nodefony/framework 10.0.0-beta.2 → 10.0.0-beta.4

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.
Files changed (76) hide show
  1. package/README.md +4 -0
  2. package/dist/_virtual/{_@oxc-project_runtime@0.152.0 → _@oxc-project_runtime@0.155.0}/helpers/esm/decorate.js +1 -2
  3. package/dist/index.js +15 -20
  4. package/dist/nodefony/config/config.js +1 -2
  5. package/dist/nodefony/config/defineModuleConfig.js +1 -2
  6. package/dist/nodefony/controller/AdminApiController.js +45 -11
  7. package/dist/nodefony/controller/ApiKeyController.js +18 -10
  8. package/dist/nodefony/controller/BenchController.js +1 -2
  9. package/dist/nodefony/controller/IssuerMetadataController.js +1 -2
  10. package/dist/nodefony/controller/LoginPageController.js +117 -0
  11. package/dist/nodefony/controller/OAuth2Controller.js +133 -17
  12. package/dist/nodefony/controller/ProtectedResourceMetadataController.js +1 -2
  13. package/dist/nodefony/controller/SessionAuthController.js +50 -13
  14. package/dist/nodefony/controller/TokenAuthController.js +14 -8
  15. package/dist/nodefony/controller/TotpController.js +7 -8
  16. package/dist/nodefony/controller/WebAuthnController.js +28 -12
  17. package/dist/nodefony/controller/oauthAuthority.js +1 -2
  18. package/dist/nodefony/decorators/routerDecorators.js +268 -65
  19. package/dist/nodefony/service/AdminBroker.js +4 -6
  20. package/dist/nodefony/service/Eta.js +1 -2
  21. package/dist/nodefony/service/IdempotencyStore.js +4 -6
  22. package/dist/nodefony/service/router.js +97 -34
  23. package/dist/nodefony/src/Controller.js +71 -43
  24. package/dist/nodefony/src/FrameworkAdminApi.js +33 -11
  25. package/dist/nodefony/src/KernelAdminApi.js +82 -18
  26. package/dist/nodefony/src/PlaygroundAdminApi.js +72 -3
  27. package/dist/nodefony/src/RedisIdempotencyStore.js +46 -4
  28. package/dist/nodefony/src/Resolver.js +105 -36
  29. package/dist/nodefony/src/ResourceController.js +2 -3
  30. package/dist/nodefony/src/Route.js +54 -8
  31. package/dist/nodefony/src/SecurityApiController.js +23 -0
  32. package/dist/nodefony/src/SyslogAdminApi.js +1 -2
  33. package/dist/nodefony/src/Template.js +1 -2
  34. package/dist/nodefony/src/configMutation.js +1 -2
  35. package/dist/nodefony/src/docsReader.js +39 -23
  36. package/dist/nodefony/src/idempotency.js +14 -22
  37. package/dist/nodefony/src/idempotencyGc.js +1 -2
  38. package/dist/nodefony/src/idempotencyStoreRegistry.js +1 -2
  39. package/dist/nodefony/src/loginPage.js +430 -0
  40. package/dist/nodefony/src/requireAuthentication.js +35 -0
  41. package/dist/nodefony/src/routeSchema.js +81 -0
  42. package/dist/nodefony/src/scopeCatalog.js +1 -2
  43. package/dist/nodefony/src/singletonGuard.js +1 -2
  44. package/dist/nodefony/src/syslogFilters.js +1 -2
  45. package/dist/types/index.d.ts +8 -12
  46. package/dist/types/nodefony/controller/AdminApiController.d.ts +12 -0
  47. package/dist/types/nodefony/controller/ApiKeyController.d.ts +2 -2
  48. package/dist/types/nodefony/controller/LoginPageController.d.ts +32 -0
  49. package/dist/types/nodefony/controller/OAuth2Controller.d.ts +67 -8
  50. package/dist/types/nodefony/controller/SessionAuthController.d.ts +46 -8
  51. package/dist/types/nodefony/controller/TokenAuthController.d.ts +6 -4
  52. package/dist/types/nodefony/controller/TotpController.d.ts +2 -2
  53. package/dist/types/nodefony/controller/WebAuthnController.d.ts +12 -4
  54. package/dist/types/nodefony/decorators/routerDecorators.d.ts +221 -35
  55. package/dist/types/nodefony/interfaces/IController.d.ts +2 -3
  56. package/dist/types/nodefony/interfaces/IRoute.d.ts +1 -2
  57. package/dist/types/nodefony/service/router.d.ts +40 -1
  58. package/dist/types/nodefony/src/Controller.d.ts +54 -17
  59. package/dist/types/nodefony/src/PlaygroundAdminApi.d.ts +12 -0
  60. package/dist/types/nodefony/src/Resolver.d.ts +44 -1
  61. package/dist/types/nodefony/src/ResourceController.d.ts +1 -1
  62. package/dist/types/nodefony/src/Route.d.ts +21 -1
  63. package/dist/types/nodefony/src/SecurityApiController.d.ts +17 -0
  64. package/dist/types/nodefony/src/docsReader.d.ts +10 -6
  65. package/dist/types/nodefony/src/idempotency.d.ts +12 -10
  66. package/dist/types/nodefony/src/loginPage.d.ts +144 -0
  67. package/dist/types/nodefony/src/requireAuthentication.d.ts +29 -0
  68. package/dist/types/nodefony/src/routeSchema.d.ts +112 -0
  69. package/docs/admin.md +83 -78
  70. package/docs/controller.md +112 -111
  71. package/docs/decorateurs.md +212 -163
  72. package/docs/idempotence.md +137 -135
  73. package/docs/routing.md +96 -95
  74. package/docs/templates.md +55 -55
  75. package/package.json +10 -13
  76. package/dist/_virtual/_@oxc-project_runtime@0.152.0/helpers/esm/decorateMetadata.js +0 -6
package/docs/templates.md CHANGED
@@ -44,11 +44,11 @@ flowchart LR
44
44
  Deux idées à retenir :
45
45
 
46
46
  1. **Le contrôleur lit le fichier, le moteur ne fait que rendre une chaîne.** `renderView()` résout le
47
- chemin, lit l'octet, puis passe la **source** à Eta (`Controller.renderView()`, `Controller.ts:544`).
47
+ chemin, lit l'octet, puis passe la **source** à Eta (`Controller.renderView()`, `Controller.ts#Controller.renderView`).
48
48
  Il n'y a **pas** de dossier `views/` magique connu du moteur.
49
49
  2. **L'échappement est automatique.** Une donnée interpolée par `<%= %>` est neutralisée (`<` devient
50
50
  `&lt;`) avant d'entrer dans le HTML — c'est la protection XSS, active par défaut
51
- (`autoEscape`, `Eta.ts:16`).
51
+ (`autoEscape`, `Eta.ts#defaultOption`).
52
52
 
53
53
  ## 📖 Lexique
54
54
 
@@ -87,24 +87,24 @@ site. C'est une faille **XSS**. La parade est l'**échappement** : on remplace `
87
87
  ## La vision Nodefony
88
88
 
89
89
  Nodefony a **un seul** moteur de vues : **Eta** (il remplace Twig et EJS, retirés). Le choix est
90
- documenté au source (`Eta`, `Eta.ts:34`) : écrit en TypeScript (types fournis, pas de `@types/*`), ESM
90
+ documenté au source (`Eta`, `Eta.ts#Eta`) : écrit en TypeScript (types fournis, pas de `@types/*`), ESM
91
91
  natif, échappement natif, et surtout des délimiteurs `<% %>` qui **n'entrent pas en collision** avec la
92
92
  syntaxe TS/JSON/JSX — décisif car le même moteur sert aussi à générer du code (le scaffold `create`).
93
93
 
94
94
  Le branchement est **délibérément minimal** :
95
95
 
96
96
  - Le service Eta est enregistré au boot sous le nom `template` (`@services([Router, Eta, …])`,
97
- `nodefony/framework/index.ts:76`) ; chaque contrôleur le récupère à sa construction
98
- (`this.get<Eta>("template")`, `Controller.ts:253`).
97
+ `nodefony/framework/index.ts`) ; chaque contrôleur le récupère à sa construction
98
+ (`this.get<Eta>("template")`, `Controller.ts#Controller.route`).
99
99
  - Le moteur ne connaît **que le rendu d'une chaîne** : `Eta.render(source, data)` appelle
100
- `renderStringAsync` (`Eta.ts:51`). C'est le contrôleur qui lit le fichier — pas Eta.
100
+ `renderStringAsync` (`Eta.ts#Eta.render`). C'est le contrôleur qui lit le fichier — pas Eta.
101
101
  - Deux options seulement sont posées, plus le cache : `autoEscape`, `useWith`, `cache`
102
- (`defaultOption`, `Eta.ts:15`). Il n'y a **pas** de racine `views/`, donc **pas** de résolution
102
+ (`defaultOption`, `Eta.ts#defaultOption`). Il n'y a **pas** de racine `views/`, donc **pas** de résolution
103
103
  d'`include`/layout par nom (voir Pièges).
104
104
 
105
105
  > [!NOTE]
106
106
  > Le rendu **d'erreurs** ne passe **pas** par les templates : une exception devient un corps **JSON
107
- > structuré** (`ErrorRenderer.renderHttp()`, `error-renderer.ts:473`), jamais une page Eta. Le moteur
107
+ > structuré** (`ErrorRenderer.renderHttp()`, `error-renderer.ts#DefaultErrorRenderer.renderHttp`), jamais une page Eta. Le moteur
108
108
  > de vues ne sert que le HTML **que tu rends explicitement**.
109
109
 
110
110
  ## 🚀 Démarrage rapide
@@ -187,17 +187,17 @@ curl -s 'http://localhost:5151/hello/%3Cb%3Ex%3C%2Fb%3E'
187
187
  > [!TIP]
188
188
  > Tu n'as écrit **aucun** appel d'envoi (`send`, `res.end`). `renderView()` produit le corps **et**
189
189
  > l'envoie. Pour piloter l'envoi toi-même, retourne plutôt une chaîne via `render()`
190
- > (`Controller.render()`, `Controller.ts:485`).
190
+ > (`Controller.render()`, `Controller.ts#Controller.render`).
191
191
 
192
192
  ## 🏗️ Architecture interne — le parcours d'un `renderView()`
193
193
 
194
194
  Deux classes, une responsabilité chacune :
195
195
 
196
- - **`Template`** (`Template.ts:2`) — la base : elle étend `Service` (donc container + logs), garde une
196
+ - **`Template`** (`Template.ts#Template`) — la base : elle étend `Service` (donc container + logs), garde une
197
197
  référence au `module` et **décide du cache** selon l'environnement (`this.cache` vrai en `prod`,
198
- `Template.ts:20`).
199
- - **`Eta`** (`Eta.ts:34`) — l'implémentation : elle instancie le moteur `eta` (`new EtaEngine()`,
200
- `Eta.ts:38`), applique le cache calculé par `Template` (`this.engine.configure()`, `Eta.ts:41`), et
198
+ `Template.ts#Template.constructor`).
199
+ - **`Eta`** (`Eta.ts#Eta`) — l'implémentation : elle instancie le moteur `eta` (`new EtaEngine()`,
200
+ `Eta.ts#Eta.constructor`), applique le cache calculé par `Template` (`this.engine.configure()`, `Eta.ts#Eta.constructor`), et
201
201
  expose deux méthodes de rendu.
202
202
 
203
203
  Le trajet d'un appel, étape par étape :
@@ -216,17 +216,17 @@ sequenceDiagram
216
216
  C->>Ctx: setContextHtml() puis renderResponse(html)
217
217
  ```
218
218
 
219
- | # | Étape | Où |
220
- | --- | -------------------------------------------- | ------------------------------------------------------------- |
221
- | 1 | Résolution + lecture async du fichier | `FileClass` dans `renderView()` (`Controller.ts:544`) |
222
- | 2 | Ouverture de la phase mesurée `render` | `phaseStart("render")` (`Controller.ts:485`) |
223
- | 3 | Injection des aides frontend dans les locals | `withFrontendLocals()` (`Controller.ts:562`) |
224
- | 4 | Rendu de la source par le moteur | `Eta.render()` → `renderStringAsync` (`Eta.ts:51`) |
225
- | 5 | `Content-Type: text/html` puis envoi | `setContextHtml()` + `renderResponse()` (`Controller.ts:523`) |
219
+ | # | Étape | Où |
220
+ | --- | -------------------------------------------- | ----------------------------------------------------------------------------------- |
221
+ | 1 | Résolution + lecture async du fichier | `FileClass` dans `renderView()` (`Controller.ts#Controller.renderView`) |
222
+ | 2 | Ouverture de la phase mesurée `render` | `phaseStart("render")` (`Controller.ts#Controller.render`) |
223
+ | 3 | Injection des aides frontend dans les locals | `withFrontendLocals()` (`Controller.ts#Controller.withFrontendLocals`) |
224
+ | 4 | Rendu de la source par le moteur | `Eta.render()` → `renderStringAsync` (`Eta.ts#Eta.render`) |
225
+ | 5 | `Content-Type: text/html` puis envoi | `setContextHtml()` + `renderResponse()` (`Controller.ts#Controller.renderResponse`) |
226
226
 
227
227
  Le point notable de l'étape 3 : `withFrontendLocals()` ajoute automatiquement `frontendTags`,
228
228
  `frontendDocument` et `asset` aux locals **si** le service `frontend` est présent — et **tes** valeurs
229
- priment (spread `param` en dernier, `Controller.ts:546`). Si le module frontend n'est pas chargé, la
229
+ priment (spread `param` en dernier, `Controller.ts#Controller.renderView`). Si le module frontend n'est pas chargé, la
230
230
  fonction retourne les locals inchangés : zéro couplage dur.
231
231
 
232
232
  ## 🔐 Sécurité — échappement HTML et XSS
@@ -239,7 +239,7 @@ La règle Eta se lit sur les délimiteurs. Trois formes, trois comportements :
239
239
  | `<%~ v %>` | interpole `v` **brut** | non | du HTML de confiance que TU produis (fragments) |
240
240
  | `<% … %>` | exécute du code (if/for…) | n/a | logique de template (pas de sortie directe) |
241
241
 
242
- L'échappement par défaut vient de l'option `autoEscape: true` posée dans `defaultOption` (`Eta.ts:16`).
242
+ L'échappement par défaut vient de l'option `autoEscape: true` posée dans `defaultOption` (`Eta.ts#defaultOption`).
243
243
  Concrètement, `<%= %>` passe la valeur dans la fonction d'échappement d'Eta, qui remplace `& < > " '`
244
244
  par leurs entités HTML. Une chaîne d'attaque comme `<script>alert(1)</script>` ressort donc en texte
245
245
  inerte `&lt;script&gt;alert(1)&lt;/script&gt;`.
@@ -255,22 +255,22 @@ Deux niveaux : ce que le **service Eta** expose, et ce que le **contrôleur** t'
255
255
 
256
256
  ### Le service `Eta` (nom d'injection `template`)
257
257
 
258
- | Méthode | Rôle | Ancre |
259
- | ------------------------- | ---------------------------------------------------------- | ----------- |
260
- | `render(source, data?)` | Rend un template depuis une **chaîne** (chemin chaud) | `Eta.ts:51` |
261
- | `renderFile(path, data?)` | Lit un fichier `.eta` **puis** le rend (usages CLI/outils) | `Eta.ts:66` |
258
+ | Méthode | Rôle | Ancre |
259
+ | ------------------------- | ---------------------------------------------------------- | ----------------------- |
260
+ | `render(source, data?)` | Rend un template depuis une **chaîne** (chemin chaud) | `Eta.ts#Eta.render` |
261
+ | `renderFile(path, data?)` | Lit un fichier `.eta` **puis** le rend (usages CLI/outils) | `Eta.ts#Eta.renderFile` |
262
262
 
263
263
  `render()` est ce qu'appelle le contrôleur ; `renderFile()` lit lui-même le fichier
264
- (`readFile` + `renderStringAsync`, `Eta.ts:71`) pour les usages qui partent d'un chemin (générateurs,
264
+ (`readFile` + `renderStringAsync`, `Eta.ts#Eta.renderFile`) pour les usages qui partent d'un chemin (générateurs,
265
265
  scaffold). Les deux sont **asynchrones** (I/O non bloquante).
266
266
 
267
267
  ### Les helpers du contrôleur
268
268
 
269
- | Helper | Pour… | Ancre |
270
- | ----------------------------------- | ------------------------------------------------------- | ------------------- |
271
- | `renderView(path, locals, status?)` | Rendre une vue `.eta` (lit le fichier + aides frontend) | `Controller.ts:524` |
272
- | `render(data, encoding?, status?)` | Envoyer un corps quelconque (ex. HTML déjà prêt) | `Controller.ts:485` |
273
- | `renderJson(obj, status?)` | Réponse JSON explicite (pas un template) | `Controller.ts:629` |
269
+ | Helper | Pour… | Ancre |
270
+ | ----------------------------------- | ------------------------------------------------------- | ------------------------------------- |
271
+ | `renderView(path, locals, status?)` | Rendre une vue `.eta` (lit le fichier + aides frontend) | `Controller.ts#Controller.render` |
272
+ | `render(data, encoding?, status?)` | Envoyer un corps quelconque (ex. HTML déjà prêt) | `Controller.ts#Controller.render` |
273
+ | `renderJson(obj, status?)` | Réponse JSON explicite (pas un template) | `Controller.ts#Controller.renderJson` |
274
274
 
275
275
  Les signatures exactes vivent dans le graphe symbolique `.ai/symbols.json` — jamais recopiées ici.
276
276
 
@@ -278,14 +278,14 @@ Les signatures exactes vivent dans le graphe symbolique `.ai/symbols.json` — j
278
278
 
279
279
  Le moteur est configuré **en dur**, pas via un bloc Zod exposé à `use()`. Trois réglages seulement :
280
280
 
281
- | Réglage | Valeur Nodefony | Effet | Ancre |
282
- | ------------ | ----------------------------- | ------------------------------------------------------------------- | ---------------- |
283
- | `autoEscape` | `true` | `<%= %>` échappe le HTML par défaut (anti-XSS) | `Eta.ts:16` |
284
- | `useWith` | `true` | locals exposés nus (`<%= name %>`) — DX façon EJS | `Eta.ts:17` |
285
- | `cache` | `true` en prod, `false` sinon | compile-once des templates en production ; recompile à chaud en dev | `Template.ts:20` |
281
+ | Réglage | Valeur Nodefony | Effet | Ancre |
282
+ | ------------ | ----------------------------- | ------------------------------------------------------------------- | ---------------------------------- |
283
+ | `autoEscape` | `true` | `<%= %>` échappe le HTML par défaut (anti-XSS) | `Eta.ts#defaultOption` |
284
+ | `useWith` | `true` | locals exposés nus (`<%= name %>`) — DX façon EJS | `Eta.ts#defaultOption` |
285
+ | `cache` | `true` en prod, `false` sinon | compile-once des templates en production ; recompile à chaud en dev | `Template.ts#Template.constructor` |
286
286
 
287
287
  Le cache n'est **pas** un booléen figé : `Template` le dérive de l'environnement du kernel
288
- (`environment === "prod"`, `Template.ts:20`) puis `Eta` l'applique au moteur (`Eta.ts:34`). En
288
+ (`environment === "prod"`, `Template.ts#Template.constructor`) puis `Eta` l'applique au moteur (`Eta.ts#Eta`). En
289
289
  développement, un template modifié est donc pris en compte sans redémarrer.
290
290
 
291
291
  ## 🔌 HTTP et WebSocket — le même rendu
@@ -306,11 +306,11 @@ c'est le différenciateur Nodefony : une classe, deux transports, le même moteu
306
306
 
307
307
  ## 📜 Normes appliquées
308
308
 
309
- | Domaine | Norme / référence | Comment le code s'y conforme |
310
- | ------------------ | ----------------------- | --------------------------------------------------------------------- |
311
- | Neutralisation XSS | OWASP — Output Encoding | échappement HTML par défaut (`autoEscape`, `Eta.ts:16`) |
312
- | Type de média HTML | `text/html` | posé par `setContextHtml()` dans `renderView()` (`Controller.ts:544`) |
313
- | I/O non bloquante | Node.js async fs | lecture async du fichier (`readFile`, `Eta.ts:71`) |
309
+ | Domaine | Norme / référence | Comment le code s'y conforme |
310
+ | ------------------ | ----------------------- | --------------------------------------------------------------------------------------- |
311
+ | Neutralisation XSS | OWASP — Output Encoding | échappement HTML par défaut (`autoEscape`, `Eta.ts#defaultOption`) |
312
+ | Type de média HTML | `text/html` | posé par `setContextHtml()` dans `renderView()` (`Controller.ts#Controller.renderView`) |
313
+ | I/O non bloquante | Node.js async fs | lecture async du fichier (`readFile`, `Eta.ts#Eta.renderFile`) |
314
314
 
315
315
  ## ⚡ Performance et mémoire
316
316
 
@@ -318,13 +318,13 @@ Le rendu de vue est la partie **réellement coûteuse** d'une réponse (lecture
318
318
  template), et le framework l'isole pour ça :
319
319
 
320
320
  - **Phase dédiée** : `renderView()` chronomètre le rendu sous la phase `render`
321
- (`phaseStart("render")`, `Controller.ts:524`) — distincte de `action` et de `send`. On voit ainsi si
321
+ (`phaseStart("render")`, `Controller.ts#Controller.render`) — distincte de `action` et de `send`. On voit ainsi si
322
322
  le temps part dans le moteur ou dans l'écriture réseau.
323
323
  - **Cache en prod** : les templates sont compilés une fois (`cache` vrai en production,
324
- `Template.ts:20`) ; le coût de parsing n'est payé qu'au premier rendu.
324
+ `Template.ts#Template.cache`) ; le coût de parsing n'est payé qu'au premier rendu.
325
325
  - **Lecture non bloquante** : le fichier est lu en async (`FileClass.readAsync()` côté `renderView`,
326
- `readFile` côté `renderFile`, `Eta.ts:66`) — l'event loop n'est jamais gelé par un `readFileSync`.
327
- - **Aides frontend paresseuses** : `withFrontendLocals()` (`Controller.ts:562`) ne construit les
326
+ `readFile` côté `renderFile`, `Eta.ts#Eta.renderFile`) — l'event loop n'est jamais gelé par un `readFileSync`.
327
+ - **Aides frontend paresseuses** : `withFrontendLocals()` (`Controller.ts#Controller.withFrontendLocals`) ne construit les
328
328
  fonctions `frontendTags`/`asset` que si le service `frontend` répond — sinon il rend les locals tels
329
329
  quels, zéro allocation superflue.
330
330
 
@@ -337,14 +337,14 @@ template), et le framework l'isole pour ça :
337
337
 
338
338
  ## ⚠️ Pièges (symptôme → cause → correction)
339
339
 
340
- | Symptôme | Cause (dans le code) | Correction |
341
- | -------------------------------------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
342
- | `<%~ include("partial") %>` ne trouve pas la vue | Aucune racine `views/` n'est configurée (`defaultOption`, `Eta.ts:15`) | Compose côté contrôleur : rends chaque fragment, ou passe le HTML en local |
343
- | Un `<b>` d'utilisateur s'exécute dans la page | Sortie brute `<%~ %>` sur une donnée non fiable | Utiliser `<%= %>` (échappé par défaut) |
344
- | `<%= it.name %>` requis alors qu'on attend `<%= name %>` | `useWith` mal compris — Nodefony l'active (`Eta.ts:17`), les locals sont nus | Écrire `<%= name %>` directement |
345
- | Modif de template ignorée en prod | `cache: true` en production (`Template.ts:20`) | Redémarrer le pod ; en dev le cache est off, recompile à chaud |
346
- | La réponse d'erreur n'est pas ma vue Eta | Les erreurs rendent du JSON, pas un template (`error-renderer.ts:109`) | Pour une page d'erreur HTML, rendre explicitement une vue dans un handler |
347
- | `renderView()` rejette et logge une ERROR | Fichier introuvable ou template invalide (le `catch` re-lève, `Controller.ts:544`) | Vérifier le chemin résolu (`resolve(module.path, …)`) |
340
+ | Symptôme | Cause (dans le code) | Correction |
341
+ | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
342
+ | `<%~ include("partial") %>` ne trouve pas la vue | Aucune racine `views/` n'est configurée (`defaultOption`, `Eta.ts#defaultOption`) | Compose côté contrôleur : rends chaque fragment, ou passe le HTML en local |
343
+ | Un `<b>` d'utilisateur s'exécute dans la page | Sortie brute `<%~ %>` sur une donnée non fiable | Utiliser `<%= %>` (échappé par défaut) |
344
+ | `<%= it.name %>` requis alors qu'on attend `<%= name %>` | `useWith` mal compris — Nodefony l'active (`Eta.ts#defaultOption`), les locals sont nus | Écrire `<%= name %>` directement |
345
+ | Modif de template ignorée en prod | `cache: true` en production (`Template.ts#Template.constructor`) | Redémarrer le pod ; en dev le cache est off, recompile à chaud |
346
+ | La réponse d'erreur n'est pas ma vue Eta | Les erreurs rendent du JSON, pas un template (`error-renderer.ts#IValidationField.message`) | Pour une page d'erreur HTML, rendre explicitement une vue dans un handler |
347
+ | `renderView()` rejette et logge une ERROR | Fichier introuvable ou template invalide (le `catch` re-lève, `Controller.ts#Controller.renderResponse`) | Vérifier le chemin résolu (`resolve(module.path, …)`) |
348
348
 
349
349
  ## 🧪 Tests et couverture
350
350
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodefony/framework",
3
- "version": "10.0.0-beta.2",
3
+ "version": "10.0.0-beta.4",
4
4
  "description": "Le modèle de programmation Nodefony : routeur, contrôleurs, décorateurs et vues — HTTP et WebSocket dans le même contexte",
5
5
  "author": "Christophe CAMENSULI <ccamensuli@gmail.com>",
6
6
  "main": "./dist/index.js",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "private": false,
27
27
  "engines": {
28
- "node": ">=24.0.0"
28
+ "node": ">=24.14.0"
29
29
  },
30
30
  "keywords": [
31
31
  "nodefony",
@@ -44,29 +44,26 @@
44
44
  "directory": "src/packages/@nodefony/framework"
45
45
  },
46
46
  "dependencies": {
47
- "@graphql-tools/merge": "9.2.6",
48
- "@graphql-tools/schema": "10.1.3",
49
47
  "eta": "4.6.0",
50
- "graphql": "17.0.2",
51
48
  "reflect-metadata": "0.2.2",
52
49
  "tslib": "2.8.1"
53
50
  },
54
51
  "devDependencies": {
55
- "@nodefony/http": "^10.0.0-beta.2",
52
+ "@nodefony/http": "^10.0.0-beta.4",
56
53
  "@types/chai": "5.2.3",
57
- "@types/node": "26.6.3",
58
- "@vitest/coverage-v8": "5.0.3",
59
- "nodefony": "^10.0.0-beta.2",
54
+ "@types/node": "26.6.5",
55
+ "@vitest/coverage-v8": "5.0.5",
56
+ "nodefony": "^10.0.0-beta.4",
60
57
  "tsx": "4.23.15",
61
- "vitest": "5.0.3"
58
+ "vitest": "5.0.5"
62
59
  },
63
60
  "license": "Apache-2.0",
64
61
  "readmeFilename": "README.md",
65
62
  "contributors": [],
66
63
  "peerDependencies": {
67
- "@nodefony/http": "^10.0.0-beta.2",
68
- "nodefony": "^10.0.0-beta.2",
69
- "zod": "^4.6.5"
64
+ "@nodefony/http": "^10.0.0-beta.4",
65
+ "nodefony": "^10.0.0-beta.4",
66
+ "zod": "^4.6.7"
70
67
  },
71
68
  "files": [
72
69
  "dist",
@@ -1,6 +0,0 @@
1
- //#region \0@oxc-project+runtime@0.152.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 };