@nodefony/framework 10.0.0-alpha.1
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/LICENSE +544 -0
- package/README.md +50 -0
- package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorate.js +9 -0
- package/dist/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/decorateMetadata.js +6 -0
- package/dist/index.js +211 -0
- package/dist/nodefony/config/config.js +61 -0
- package/dist/nodefony/config/defineModuleConfig.js +36 -0
- package/dist/nodefony/controller/AdminApiController.js +163 -0
- package/dist/nodefony/controller/ApiKeyController.js +151 -0
- package/dist/nodefony/controller/BenchController.js +132 -0
- package/dist/nodefony/controller/IssuerMetadataController.js +148 -0
- package/dist/nodefony/controller/OAuth2Controller.js +133 -0
- package/dist/nodefony/controller/ProtectedResourceMetadataController.js +221 -0
- package/dist/nodefony/controller/SessionAuthController.js +141 -0
- package/dist/nodefony/controller/TokenAuthController.js +113 -0
- package/dist/nodefony/controller/TotpController.js +129 -0
- package/dist/nodefony/controller/WebAuthnController.js +242 -0
- package/dist/nodefony/controller/oauthAuthority.js +74 -0
- package/dist/nodefony/decorators/routerDecorators.js +967 -0
- package/dist/nodefony/interfaces/IAdminBroker.js +1 -0
- package/dist/nodefony/interfaces/IController.js +1 -0
- package/dist/nodefony/interfaces/IIdempotencyStore.js +1 -0
- package/dist/nodefony/interfaces/IResolver.js +1 -0
- package/dist/nodefony/interfaces/IRoute.js +1 -0
- package/dist/nodefony/interfaces/index.js +1 -0
- package/dist/nodefony/service/AdminBroker.js +106 -0
- package/dist/nodefony/service/Eta.js +68 -0
- package/dist/nodefony/service/IdempotencyStore.js +136 -0
- package/dist/nodefony/service/router.js +243 -0
- package/dist/nodefony/src/Controller.js +515 -0
- package/dist/nodefony/src/FrameworkAdminApi.js +268 -0
- package/dist/nodefony/src/KernelAdminApi.js +1243 -0
- package/dist/nodefony/src/PlaygroundAdminApi.js +97 -0
- package/dist/nodefony/src/RedisIdempotencyStore.js +254 -0
- package/dist/nodefony/src/Resolver.js +416 -0
- package/dist/nodefony/src/ResourceController.js +148 -0
- package/dist/nodefony/src/Route.js +476 -0
- package/dist/nodefony/src/SyslogAdminApi.js +466 -0
- package/dist/nodefony/src/Template.js +15 -0
- package/dist/nodefony/src/configMutation.js +186 -0
- package/dist/nodefony/src/docsReader.js +929 -0
- package/dist/nodefony/src/idempotency.js +137 -0
- package/dist/nodefony/src/idempotencyGc.js +32 -0
- package/dist/nodefony/src/idempotencyStoreRegistry.js +36 -0
- package/dist/nodefony/src/scopeCatalog.js +40 -0
- package/dist/nodefony/src/syslogFilters.js +51 -0
- package/dist/types/index.d.ts +96 -0
- package/dist/types/nodefony/config/config.d.ts +41 -0
- package/dist/types/nodefony/config/defineModuleConfig.d.ts +27 -0
- package/dist/types/nodefony/controller/AdminApiController.d.ts +70 -0
- package/dist/types/nodefony/controller/ApiKeyController.d.ts +49 -0
- package/dist/types/nodefony/controller/BenchController.d.ts +45 -0
- package/dist/types/nodefony/controller/IssuerMetadataController.d.ts +86 -0
- package/dist/types/nodefony/controller/OAuth2Controller.d.ts +81 -0
- package/dist/types/nodefony/controller/ProtectedResourceMetadataController.d.ts +147 -0
- package/dist/types/nodefony/controller/SessionAuthController.d.ts +74 -0
- package/dist/types/nodefony/controller/TokenAuthController.d.ts +56 -0
- package/dist/types/nodefony/controller/TotpController.d.ts +42 -0
- package/dist/types/nodefony/controller/WebAuthnController.d.ts +123 -0
- package/dist/types/nodefony/controller/oauthAuthority.d.ts +54 -0
- package/dist/types/nodefony/decorators/routerDecorators.d.ts +632 -0
- package/dist/types/nodefony/interfaces/IAdminBroker.d.ts +79 -0
- package/dist/types/nodefony/interfaces/IController.d.ts +38 -0
- package/dist/types/nodefony/interfaces/IIdempotencyStore.d.ts +1 -0
- package/dist/types/nodefony/interfaces/IResolver.d.ts +25 -0
- package/dist/types/nodefony/interfaces/IRoute.d.ts +31 -0
- package/dist/types/nodefony/interfaces/index.d.ts +5 -0
- package/dist/types/nodefony/service/AdminBroker.d.ts +37 -0
- package/dist/types/nodefony/service/Eta.d.ts +25 -0
- package/dist/types/nodefony/service/IdempotencyStore.d.ts +45 -0
- package/dist/types/nodefony/service/router.d.ts +53 -0
- package/dist/types/nodefony/src/Controller.d.ts +193 -0
- package/dist/types/nodefony/src/FrameworkAdminApi.d.ts +35 -0
- package/dist/types/nodefony/src/KernelAdminApi.d.ts +71 -0
- package/dist/types/nodefony/src/PlaygroundAdminApi.d.ts +98 -0
- package/dist/types/nodefony/src/RedisIdempotencyStore.d.ts +104 -0
- package/dist/types/nodefony/src/Resolver.d.ts +165 -0
- package/dist/types/nodefony/src/ResourceController.d.ts +171 -0
- package/dist/types/nodefony/src/Route.d.ts +192 -0
- package/dist/types/nodefony/src/SyslogAdminApi.d.ts +38 -0
- package/dist/types/nodefony/src/Template.d.ts +8 -0
- package/dist/types/nodefony/src/configMutation.d.ts +109 -0
- package/dist/types/nodefony/src/docsReader.d.ts +369 -0
- package/dist/types/nodefony/src/idempotency.d.ts +96 -0
- package/dist/types/nodefony/src/idempotencyGc.d.ts +30 -0
- package/dist/types/nodefony/src/idempotencyStoreRegistry.d.ts +59 -0
- package/dist/types/nodefony/src/scopeCatalog.d.ts +26 -0
- package/dist/types/nodefony/src/syslogFilters.d.ts +52 -0
- package/docs/admin.md +451 -0
- package/docs/controller.md +645 -0
- package/docs/decorateurs.md +845 -0
- package/docs/idempotence.md +741 -0
- package/docs/index.md +151 -0
- package/docs/routing.md +648 -0
- package/docs/templates.md +380 -0
- package/package.json +83 -0
package/docs/index.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "@nodefony/framework — routes, contrôleurs, décorateurs"
|
|
3
|
+
navTitle: "@nodefony/framework"
|
|
4
|
+
lang: fr
|
|
5
|
+
module: "@nodefony/framework"
|
|
6
|
+
topic: framework
|
|
7
|
+
section: "Cœur runtime"
|
|
8
|
+
audience: [developer]
|
|
9
|
+
tags: [router, controller, decorateurs, resolver, routing, idempotence, admin]
|
|
10
|
+
version: "doc"
|
|
11
|
+
status: stable
|
|
12
|
+
updated: 2026-07-19
|
|
13
|
+
source: "src/packages/@nodefony/framework/docs/index.md"
|
|
14
|
+
coverageModule: framework
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# @nodefony/framework — routes, contrôleurs, décorateurs
|
|
18
|
+
|
|
19
|
+
> C'est ici qu'on écrit son application. `@nodefony/http` construit le contexte d'une requête ; ce
|
|
20
|
+
> module décide **quoi en faire** : quelle route, quel contrôleur, quelle action, avec quels droits.
|
|
21
|
+
> Il porte la DX du framework — les décorateurs — et ses invariants — résolution ordonnée, idempotence,
|
|
22
|
+
> data plane d'administration. Un contrôleur y déclare ses actions **HTTP et WebSocket avec les mêmes
|
|
23
|
+
> décorateurs**.
|
|
24
|
+
|
|
25
|
+
📍 [Documentation](../../../../../docs/index.md) › **@nodefony/framework**
|
|
26
|
+
|
|
27
|
+
## 🧭 Par où commencer
|
|
28
|
+
|
|
29
|
+
Trois parcours selon ce que tu viens faire. L'ordre compte : chaque étape suppose la précédente.
|
|
30
|
+
|
|
31
|
+
**J'écris ma première route** — le chemin le plus court vers une application qui répond.
|
|
32
|
+
|
|
33
|
+
1. [Décorateurs](decorateurs.md) — la surface que tu tapes : `@controller`, `@Get`, `@Body`, `@Param`.
|
|
34
|
+
**Commence ici**, c'est la table de référence.
|
|
35
|
+
2. [Contrôleurs](controller.md) — ce dont tu hérites, comment répondre, comment échouer proprement.
|
|
36
|
+
3. [Routage](routing.md) — pourquoi telle route gagne sur telle autre, et comment lire un `405`.
|
|
37
|
+
|
|
38
|
+
**Je débugge une route qui ne répond pas comme prévu.**
|
|
39
|
+
|
|
40
|
+
1. [Routage](routing.md) — l'ordre de déclaration **est** la priorité ; la passe 405 ; les vhosts.
|
|
41
|
+
2. [Contrôleurs](controller.md) — l'ordre réel du cycle de vie, et ce que `initialize()` peut ou non
|
|
42
|
+
supposer.
|
|
43
|
+
3. [Pipeline de requête](../../../../../docs/architecture/pipeline-requete.md) — ce qui s'est passé
|
|
44
|
+
avant que ta route soit même consultée.
|
|
45
|
+
|
|
46
|
+
**Je fiabilise des mutations** — paiements, commandes, tout ce qu'on ne veut pas jouer deux fois.
|
|
47
|
+
|
|
48
|
+
1. [Idempotence](idempotence.md) — `@Idempotent`, la clé, les stores, ce qui se passe au rejeu.
|
|
49
|
+
2. [Contrôleurs](controller.md) — codes de retour et réponses vides (204) sans piège.
|
|
50
|
+
3. [Sécurité](../../security/docs/index.md) — l'autorisation qui va avec.
|
|
51
|
+
|
|
52
|
+
## 🗂️ Les briques du module
|
|
53
|
+
|
|
54
|
+
Le tableau pour choisir vite ; les cards en dessous pour savoir ce qu'on y trouve.
|
|
55
|
+
|
|
56
|
+
| Brique | Ce qu'elle résout | Tu en as besoin quand… |
|
|
57
|
+
| ------------------------------- | -------------------------------------------------- | --------------------------------------------------------- |
|
|
58
|
+
| [Décorateurs](decorateurs.md) | déclarer routes, paramètres, réponses, gardes | toujours — c'est la surface d'écriture |
|
|
59
|
+
| [Contrôleurs](controller.md) | recevoir la requête, répondre, gérer l'erreur | toujours |
|
|
60
|
+
| [Routage](routing.md) | apparier une URL à une action, arbitrer, expliquer | deux routes se disputent, ou un 404/405 surprend |
|
|
61
|
+
| [Idempotence](idempotence.md) | empêcher le double effet d'une mutation rejouée | paiement, commande, tout effet non rejouable |
|
|
62
|
+
| [Admin (data plane)](admin.md) | monter les API d'admin `/nodefony/<ns>/api/*` | ton module expose des stats ou actions à Studio et au CLI |
|
|
63
|
+
| [Templates (Eta)](templates.md) | rendre des vues HTML côté serveur | tu renvoies des pages HTML plutôt que du JSON |
|
|
64
|
+
|
|
65
|
+
```nodefony-cards
|
|
66
|
+
[
|
|
67
|
+
{ "icon": "🏷️", "title": "decorateurs", "href": "decorateurs.md",
|
|
68
|
+
"desc": "La table de référence complète — classe, méthode HTTP, paramètre, réponse, sécurité, WebSocket — chacun avec son effet et un exemple court.",
|
|
69
|
+
"meta": "la page qu'on garde ouverte en écrivant un contrôleur" },
|
|
70
|
+
{ "icon": "🎛️", "title": "controller", "href": "controller.md",
|
|
71
|
+
"desc": "Ce dont hérite un contrôleur, d'où viennent request / response / session, comment répondre (auto-JSON, codes, flux de fichiers), comment les erreurs remontent, et l'ordre réel du cycle de vie.",
|
|
72
|
+
"meta": "toujours — c'est ce dont tu hérites" },
|
|
73
|
+
{ "icon": "🚦", "title": "routing", "href": "routing.md",
|
|
74
|
+
"desc": "Une table ordonnée où le premier motif qui correspond gagne : l'arbitrage sans score de spécificité, la partition littéral/dynamique qui accélère sans changer la sémantique, le 405 et son en-tête Allow, les vhosts, le duplex HTTP+WebSocket sur un même chemin.",
|
|
75
|
+
"meta": "deux routes se disputent, ou un 404/405 surprend" },
|
|
76
|
+
{ "icon": "🔁", "title": "idempotence", "href": "idempotence.md",
|
|
77
|
+
"desc": "@Idempotent, la clé d'idempotence, les trois stores et leurs capacités réelles, le GC des entrées expirées, et ce que le client observe quand il rejoue la même clé.",
|
|
78
|
+
"meta": "paiement, commande, tout effet non rejouable" },
|
|
79
|
+
{ "icon": "🛡️", "title": "admin", "href": "admin.md",
|
|
80
|
+
"desc": "Le data plane d'administration : comment un module déclare son API d'admin via AdminBroker, la convention de route /nodefony/<ns>/api/*, le RBAC fail-closed (ROLE_NODEFONY_ADMIN), le duplex HTTP/WebSocket, le catalogue et le Playground.",
|
|
81
|
+
"meta": "exposer une API d'admin cohérente CLI ↔ Web" },
|
|
82
|
+
{ "icon": "📄", "title": "templates", "href": "templates.md",
|
|
83
|
+
"desc": "Le moteur de vues Eta : rendre une vue depuis un contrôleur (renderView, render), résolution des chemins de vues, passage de variables, échappement HTML par défaut contre le XSS, rendu d'erreurs.",
|
|
84
|
+
"meta": "produire du HTML côté serveur plutôt que du JSON" }
|
|
85
|
+
]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 🏛️ Place dans le framework
|
|
89
|
+
|
|
90
|
+
```mermaid
|
|
91
|
+
flowchart LR
|
|
92
|
+
DEC["décorateurs<br/>@controller · @Get · @Param"] --> RT["Router<br/>table ordonnée de routes"]
|
|
93
|
+
RT --> RS["Resolver<br/>par requête : match → action"]
|
|
94
|
+
RS --> C["Controller<br/>ton code"]
|
|
95
|
+
C --> AB["AdminBroker<br/>/nodefony/<ns>/api/*"]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Le module s'appuie sur `@nodefony/http` (contexte, serveurs) et se fait garder par
|
|
99
|
+
`@nodefony/security` (firewall, CSRF). L'inverse n'est pas vrai : `@nodefony/http` ne peut pas
|
|
100
|
+
importer ce module — ce serait un cycle.
|
|
101
|
+
|
|
102
|
+
## 🧰 Surface publique
|
|
103
|
+
|
|
104
|
+
Depuis une application : `Controller`, `Router`, `Resolver`, `Route`, `controllers()`, les décorateurs
|
|
105
|
+
de route, de paramètre et de garde, `IdempotencyStore`, `AdminBroker`. Les signatures exactes vivent
|
|
106
|
+
dans `.ai/symbols.json` et les types générés — jamais recopiées ici, où elles se périmeraient.
|
|
107
|
+
|
|
108
|
+
## ⚙️ Configuration
|
|
109
|
+
|
|
110
|
+
Bloc Zod (`nodefony/config/config.ts`), déclaré depuis l'application via
|
|
111
|
+
`use("@nodefony/framework", { … })` : `router`, `adminBroker`, et `idempotency` (choix du store et
|
|
112
|
+
réglages du GC — détaillé dans la page [Idempotence](idempotence.md)).
|
|
113
|
+
|
|
114
|
+
## 📜 Normes appliquées
|
|
115
|
+
|
|
116
|
+
RFC 9110 (méthodes, `405` et en-tête `Allow`, redirections), RFC 6455 §7.4 (codes de fermeture
|
|
117
|
+
WebSocket, dont le `1002` d'erreur de sous-protocole), et le brouillon IETF `Idempotency-Key`.
|
|
118
|
+
|
|
119
|
+
## 📡 Observabilité — Studio
|
|
120
|
+
|
|
121
|
+
L'écran **Routes** liste la table telle qu'elle est réellement montée, et le **Playground** permet de
|
|
122
|
+
jouer une route en voyant ses badges `@IsGranted` / `@Idempotent`. Chaque module publie son data plane
|
|
123
|
+
via `AdminBroker`.
|
|
124
|
+
|
|
125
|
+
## 🧪 Tests & couverture
|
|
126
|
+
|
|
127
|
+
Les chiffres exacts vivent dans la carte de l'aperçu, régénérée depuis vitest — jamais figés ici.
|
|
128
|
+
|
|
129
|
+
| Type | Où | Ce qui est prouvé |
|
|
130
|
+
| ----------- | ------------------------ | ------------------------------------------------------- |
|
|
131
|
+
| Unitaire | `nodefony/tests/unit/**` | routeur, resolver, contrôleur, décorateurs, idempotence |
|
|
132
|
+
| Intégration | via `@nodefony/http` | la route réelle répond sur un serveur vivant |
|
|
133
|
+
| E2E | via `@nodefony/drizzle` | idempotence rejouée contre une vraie base |
|
|
134
|
+
|
|
135
|
+
## ⚠️ Pièges (symptôme → cause → correction)
|
|
136
|
+
|
|
137
|
+
| Symptôme | Cause | Correction |
|
|
138
|
+
| --------------------------------------------- | ------------------------------------------------------------ | --------------------------------------------- |
|
|
139
|
+
| `404` sur une route qui « existe » | Contrôleur jamais importé — les routes naissent à l'import | L'ajouter à `@controllers([…])` du module |
|
|
140
|
+
| Une route paramétrée mange un chemin littéral | L'ordre de déclaration **est** la priorité | Déclarer le littéral avant le paramétré |
|
|
141
|
+
| Action WebSocket jamais atteinte | Transport `WEBSOCKET` non déclaré sur la route | L'ajouter aux méthodes de la route |
|
|
142
|
+
| `ce nom est RÉSERVÉ` sur une action `remove` | Le nom entre en collision avec un membre hérité de `Service` | Renommer l'action — l'URL vient du décorateur |
|
|
143
|
+
| Double effet d'une mutation rejouée | Route sensible sans clé d'idempotence | Voir [idempotence](idempotence.md) |
|
|
144
|
+
|
|
145
|
+
## 🔗 Pour aller plus loin
|
|
146
|
+
|
|
147
|
+
- Le trajet complet d'une requête → [pipeline-requete](../../../../../docs/architecture/pipeline-requete.md)
|
|
148
|
+
- La couche transport en dessous → [@nodefony/http](../../http/docs/index.md)
|
|
149
|
+
- Le pare-feu qui garde les actions → [@nodefony/security](../../security/docs/index.md)
|
|
150
|
+
- Portées d'injection des contrôleurs → [injection-portees](../../../../../docs/architecture/injection-portees.md)
|
|
151
|
+
- Vue d'ensemble du framework → [vue-ensemble](../../../../../docs/architecture/vue-ensemble.md)
|