@nodefony/frontend 10.0.0-alpha.3 → 10.0.0-alpha.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/LICENSE +201 -543
- package/dist/_virtual/{_@oxc-project_runtime@0.148.0 → _@oxc-project_runtime@0.149.0}/helpers/esm/decorate.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.148.0 → _@oxc-project_runtime@0.149.0}/helpers/esm/decorateMetadata.js +1 -1
- package/dist/index.js +2 -2
- package/dist/nodefony/config/config.js +1 -1
- package/dist/nodefony/service/FrontendService.js +49 -20
- package/dist/nodefony/service/ViteConfigGenerator.js +2 -3
- package/dist/nodefony/service/ViteProcessSupervisor.js +1 -2
- package/dist/nodefony/src/builders/ViteBuilder.js +46 -5
- package/dist/nodefony/src/remoteDev.js +41 -14
- package/dist/nodefony/src/template/TemplateHelper.js +2 -2
- package/dist/types/index.d.ts +3 -3
- package/dist/types/nodefony/config/config.d.ts +2 -2
- package/dist/types/nodefony/config/defineModuleConfig.d.ts +2 -3
- package/dist/types/nodefony/service/FrontendService.d.ts +30 -11
- package/dist/types/nodefony/service/ViteConfigGenerator.d.ts +0 -11
- package/dist/types/nodefony/src/builders/ViteBuilder.d.ts +37 -0
- package/dist/types/nodefony/src/remoteDev.d.ts +30 -13
- package/docs/index.md +12 -12
- package/package.json +11 -11
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* NAVIGATEUR utilise peut être toute autre chose — un forwarder TLS (Codespaces,
|
|
6
6
|
* Gitpod), une passerelle de conteneur (`host.docker.internal`), un port remappé.
|
|
7
7
|
* Ce module dissocie les deux : il produit l'origine publique (assets, `base`
|
|
8
|
-
* Vite
|
|
8
|
+
* Vite) à partir d'un TEMPLATE (`{port}` substitué au port réel
|
|
9
9
|
* du spawn) — explicite (`frontend.publicOrigin`) ou détecté depuis
|
|
10
10
|
* l'environnement de la plateforme.
|
|
11
11
|
*
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* Formats VÉRIFIÉS (docs officielles + source Vite 8) :
|
|
16
16
|
* - Codespaces : `https://${CODESPACE_NAME}-${port}.${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}`
|
|
17
|
-
* (TLS terminé par le forwarder
|
|
17
|
+
* (TLS terminé par le forwarder ; le socket HMR s'en déduit côté client).
|
|
18
18
|
* - Gitpod classic : `https://${port}-<hôte de GITPOD_WORKSPACE_URL>`.
|
|
19
19
|
* - Vite `server.allowedHosts` : IP et `localhost`/`*.localhost` TOUJOURS
|
|
20
20
|
* acceptés ; un préfixe `.` = le domaine ET tous ses sous-domaines.
|
|
@@ -27,15 +27,6 @@ export declare const PORT_PLACEHOLDER = "{port}";
|
|
|
27
27
|
export interface IResolvedPublicOrigin {
|
|
28
28
|
/** Origine que le navigateur utilise — verbatim dans les `<script>` et le `base` Vite. */
|
|
29
29
|
readonly origin: string;
|
|
30
|
-
/**
|
|
31
|
-
* Config `server.hmr` cliente : le WS HMR doit suivre le MÊME chemin que les
|
|
32
|
-
* assets. Port implicite → 443/80 selon le scheme (cas forwarder TLS).
|
|
33
|
-
*/
|
|
34
|
-
readonly hmr: {
|
|
35
|
-
readonly host: string;
|
|
36
|
-
readonly clientPort: number;
|
|
37
|
-
readonly protocol: "ws" | "wss";
|
|
38
|
-
};
|
|
39
30
|
}
|
|
40
31
|
/** Environnement de dev déporté détecté depuis les variables de la plateforme. */
|
|
41
32
|
export interface IRemoteDevDetection {
|
|
@@ -51,6 +42,31 @@ export interface IRemoteDevDetection {
|
|
|
51
42
|
* sous Windows, une CONNEXION vers `0.0.0.0` échoue aussi (health check).
|
|
52
43
|
*/
|
|
53
44
|
export declare function browserReachableHost(listenHost: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Le client est-il arrivé par la BOUCLE LOCALE de la machine qui sert ?
|
|
47
|
+
*
|
|
48
|
+
* Ce n'est pas une commodité : c'est un fait vérifiable qui prime sur toute
|
|
49
|
+
* déduction faite au démarrage. Une plateforme de dev déporté se détecte par
|
|
50
|
+
* une variable d'environnement — donc UNE FOIS, au lancement du serveur — alors
|
|
51
|
+
* qu'un même serveur reçoit simultanément des clients arrivés par des chemins
|
|
52
|
+
* différents : l'origine publique de la plateforme, et un tunnel local (VS Code
|
|
53
|
+
* Desktop redirige les ports d'un Codespace sur `localhost`, c'est sa
|
|
54
|
+
* configuration par défaut).
|
|
55
|
+
*
|
|
56
|
+
* Servir l'origine publique à un client venu du tunnel a un coût réel : cette
|
|
57
|
+
* origine exige la session de la plateforme. Un navigateur humain la porte et
|
|
58
|
+
* ne voit rien ; une intégration continue, une sonde ou un agent ne l'ont pas,
|
|
59
|
+
* se font refuser, et obtiennent une page blanche que rien n'explique.
|
|
60
|
+
*
|
|
61
|
+
* La liste est FERMÉE, et c'est ce qui la rend sûre : le `Host` est une donnée
|
|
62
|
+
* cliente, et seuls ces noms désignent la machine locale de façon non
|
|
63
|
+
* ambiguë. `0.0.0.0`/`::` en sont exclus — ce sont des adresses d'écoute, pas
|
|
64
|
+
* des destinations (cf `browserReachableHost`).
|
|
65
|
+
*
|
|
66
|
+
* @param hostname - nom d'hôte NU, sans port (`[::1]` pour l'IPv6 canonique).
|
|
67
|
+
* @returns `true` si ce nom désigne la boucle locale.
|
|
68
|
+
*/
|
|
69
|
+
export declare function isLoopbackHostname(hostname: string): boolean;
|
|
54
70
|
/** Un template d'origine est-il syntaxiquement valide ? (autorité unique) */
|
|
55
71
|
export declare function isValidOriginTemplate(template: string): boolean;
|
|
56
72
|
/**
|
|
@@ -76,9 +92,10 @@ export declare function originWithHostname(origin: string, hostname: string): st
|
|
|
76
92
|
/**
|
|
77
93
|
* Résout un template d'origine contre le port RÉEL du spawn. Pure.
|
|
78
94
|
*
|
|
79
|
-
* @returns origine
|
|
95
|
+
* @returns l'origine publique, ou `null` si le template est invalide
|
|
80
96
|
* (l'appelant retombe sur la dérivation locale en l'ANNONÇANT — jamais en
|
|
81
|
-
* silence).
|
|
97
|
+
* silence). Aucune config HMR n'est rendue : le socket suit l'origine par
|
|
98
|
+
* laquelle le client Vite a été chargé, il n'a rien à recevoir.
|
|
82
99
|
*/
|
|
83
100
|
export declare function resolveOriginTemplate(template: string, port: number): IResolvedPublicOrigin | null;
|
|
84
101
|
/**
|
package/docs/index.md
CHANGED
|
@@ -370,7 +370,7 @@ JSON Schema pour l'écran de configuration de Studio.
|
|
|
370
370
|
> **`backendPort` n'est pas forcément le port écouté.** Avec une politique de port automatique, un
|
|
371
371
|
> 5151 occupé fait glisser l'écoute sur 5153. Un proxy figé enverrait alors les appels de ton
|
|
372
372
|
> interface vers le serveur d'une **autre** application. Le module lit donc le port réel sur le
|
|
373
|
-
> serveur lui-même (`FrontendService.resolveBackendPort()`, `FrontendService.ts:
|
|
373
|
+
> serveur lui-même (`FrontendService.resolveBackendPort()`, `FrontendService.ts:471`) et journalise
|
|
374
374
|
> l'écart.
|
|
375
375
|
|
|
376
376
|
### Le build de production
|
|
@@ -490,8 +490,8 @@ intermittent, apparaissant seulement quand le navigateur est plus rapide que le
|
|
|
490
490
|
| ----------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------- |
|
|
491
491
|
| `FrontendService` | l'orchestrateur : entrées, familles, cycle de vie, rendu | `FrontendService.ts:70` |
|
|
492
492
|
| `ViteProcessSupervisor` | lance, surveille, relance et arrête **un** processus Vite | `ViteProcessSupervisor.ts:215` |
|
|
493
|
-
| `ViteConfigGenerator` | écrit la configuration Vite (fonction pure, testée seule) | `ViteConfigGenerator.toMjs()` (`ViteConfigGenerator.ts:
|
|
494
|
-
| `ViteBuilder` | construit l'objet de configuration Vite pour le build en processus | `ViteBuilder.buildViteConfig()` (`ViteBuilder.ts:
|
|
493
|
+
| `ViteConfigGenerator` | écrit la configuration Vite (fonction pure, testée seule) | `ViteConfigGenerator.toMjs()` (`ViteConfigGenerator.ts:69`) |
|
|
494
|
+
| `ViteBuilder` | construit l'objet de configuration Vite pour le build en processus | `ViteBuilder.buildViteConfig()` (`ViteBuilder.ts:95`) |
|
|
495
495
|
| `TemplateHelper` | produit les balises (dev) ou lit le manifeste (prod) | `TemplateHelper.ts:36` |
|
|
496
496
|
| `isolationGroups` | à quelle famille appartient un preset, et sur quel bloc de ports | `isolationGroup()` (`isolationGroups.ts:39`) |
|
|
497
497
|
| `FrontendAdminApi` | la vue sûre de l'état, pour Studio | `buildFrontendStatus()` (`FrontendAdminApi.ts:139`) |
|
|
@@ -597,7 +597,7 @@ et dans les types du paquet — jamais recopiées ici, où elles se périmeraien
|
|
|
597
597
|
|
|
598
598
|
### `registerEntry` — la déclaration d'une interface
|
|
599
599
|
|
|
600
|
-
`FrontendService.registerEntry()` (`FrontendService.ts:
|
|
600
|
+
`FrontendService.registerEntry()` (`FrontendService.ts:243`) est appelée par le module consommateur,
|
|
601
601
|
dans son `onKernelBoot()`. Elle résout les chemins relatifs, calcule le préfixe public et renvoie
|
|
602
602
|
l'entrée résolue (`IResolvedFrontendEntry`, `IFrontBuilder.ts:40`).
|
|
603
603
|
|
|
@@ -637,7 +637,7 @@ const tags = frontend.renderTags("shop", context.cspNonce);
|
|
|
637
637
|
const html = frontend.renderDocument("shop", context.cspNonce);
|
|
638
638
|
```
|
|
639
639
|
|
|
640
|
-
`renderDocument` (`FrontendService.ts:
|
|
640
|
+
`renderDocument` (`FrontendService.ts:904`) lit l'`index.html` **de ton module**, retire le `<script>`
|
|
641
641
|
d'entrée source, injecte les balises au marqueur (ou avant `</head>`), et renvoie le document.
|
|
642
642
|
Pas d'`index.html` ? Une coquille minimale est générée. En production, l'index est mis en cache ; en
|
|
643
643
|
développement il est relu à chaque appel, pour que tes modifications de la coquille apparaissent.
|
|
@@ -650,7 +650,7 @@ Ce qui est injecté en développement (`TemplateHelper.renderDevTags()`, `Templa
|
|
|
650
650
|
3. ton entrée, servie par son **chemin absolu** (`/@fs/…`) plutôt que relatif — c'est ce qui permet à
|
|
651
651
|
deux modules d'avoir chacun leur `frontend/src/main.tsx` sans collision ;
|
|
652
652
|
4. un pont qui relaie les événements de rechargement vers la barre de débogage, **sans ouvrir de
|
|
653
|
-
seconde connexion** (`hmrBridgeTag()`, `TemplateHelper.ts:
|
|
653
|
+
seconde connexion** (`hmrBridgeTag()`, `TemplateHelper.ts:267`) ;
|
|
654
654
|
5. la barre de débogage elle-même, résolue une fois et servie via Vite (`debugBarTag()`,
|
|
655
655
|
`TemplateHelper.ts:252`).
|
|
656
656
|
|
|
@@ -660,7 +660,7 @@ l'état. Une page dégradée reste une page.
|
|
|
660
660
|
### Les helpers de vue
|
|
661
661
|
|
|
662
662
|
Si tu rends une vue Eta plutôt qu'une chaîne, trois helpers sont déjà dans tes variables locales
|
|
663
|
-
(`Controller.withFrontendLocals()`, `Controller.ts:
|
|
663
|
+
(`Controller.withFrontendLocals()`, `Controller.ts:448`) — inspirés des helpers d'assets de Symfony :
|
|
664
664
|
|
|
665
665
|
```html
|
|
666
666
|
<%~ frontendDocument("shop") %>
|
|
@@ -699,7 +699,7 @@ Quatre comportements à connaître :
|
|
|
699
699
|
les autres résultats.
|
|
700
700
|
- **Le résultat est un bilan** : construits / ignorés / en échec, journalisé et renvoyé.
|
|
701
701
|
- **Un démarrage en production sans build se répare — ou se dénonce.** `setupProd()`
|
|
702
|
-
(`FrontendService.ts:
|
|
702
|
+
(`FrontendService.ts:683`) vérifie le manifeste de chaque entrée AVANT de monter les statics.
|
|
703
703
|
Manifeste absent et Vite installé (poste de développement, devDependencies présentes) : le build
|
|
704
704
|
tourne **une fois au démarrage**, annoncé en WARNING — fini l'écran blanc après un
|
|
705
705
|
`nodefony production --detach` lancé trop tôt. Manifeste absent et Vite introuvable (image de
|
|
@@ -735,7 +735,7 @@ use("@nodefony/frontend", { assetBaseUrl: "https://cdn.example.com" });
|
|
|
735
735
|
// → <script src="https://cdn.example.com/_assets/shop/main-a1b2c3.js">
|
|
736
736
|
```
|
|
737
737
|
|
|
738
|
-
En production, `setupProd()` (`FrontendService.ts:
|
|
738
|
+
En production, `setupProd()` (`FrontendService.ts:683`) monte chaque dossier de sortie sur son
|
|
739
739
|
`publicPath` via le serveur statique — résolu **par nom**, jamais par import, pour ne pas créer de
|
|
740
740
|
cycle. Si ce service est absent (proxy frontal, CDN devant), un avertissement le dit et rien n'est
|
|
741
741
|
monté : c'est un déploiement valide, pas une panne.
|
|
@@ -765,7 +765,7 @@ Deux points d'attention avant de se lancer :
|
|
|
765
765
|
|
|
766
766
|
- le preset alimente le build en processus (`ViteBuilder`), mais la configuration du **serveur de
|
|
767
767
|
développement** est écrite par le générateur, qui possède sa propre correspondance type → greffon
|
|
768
|
-
(`ViteConfigGenerator.toMjs()`, `ViteConfigGenerator.ts:
|
|
768
|
+
(`ViteConfigGenerator.toMjs()`, `ViteConfigGenerator.ts:69`). Un nouveau type doit être ajouté aux
|
|
769
769
|
**deux** endroits, sinon il lève `FrontendPresetUnknownError` (`FrontendError.ts:19`) ;
|
|
770
770
|
- si le nouveau framework transforme des fichiers qui ne lui appartiennent pas, il lui faut sa propre
|
|
771
771
|
famille d'isolation — c'est la leçon d'Angular.
|
|
@@ -782,10 +782,10 @@ origine. Or en développement, tes modules viennent du port 5173 alors que ta pa
|
|
|
782
782
|
|
|
783
783
|
La solution retenue n'est pas d'affaiblir la politique, mais de la **composer**. Une fois Vite prêt
|
|
784
784
|
(donc ses ports réellement connus), le service déclare ses origines au pare-feu
|
|
785
|
-
(`#registerCsp()`, `FrontendService.ts:
|
|
785
|
+
(`#registerCsp()`, `FrontendService.ts:990`), qui émet **un seul** en-tête, origines fusionnées et
|
|
786
786
|
nonce par requête. À l'arrêt, les origines sont retirées et la politique redevient stricte.
|
|
787
787
|
|
|
788
|
-
Le fragment déclaré (`#viteCspFragment()`, `FrontendService.ts:
|
|
788
|
+
Le fragment déclaré (`#viteCspFragment()`, `FrontendService.ts:1012`) mérite deux explications, parce
|
|
789
789
|
qu'elles piègent tout le monde :
|
|
790
790
|
|
|
791
791
|
- **`'self'` est répété dans chaque directive.** `connect-src`, `style-src`, `img-src` et `font-src`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodefony/frontend",
|
|
3
|
-
"version": "10.0.0-alpha.
|
|
3
|
+
"version": "10.0.0-alpha.5",
|
|
4
4
|
"description": "Construction et rechargement à chaud des frontends de chaque module Nodefony — Vite intégré, multi-framework (React, Vue, Angular, Svelte)",
|
|
5
5
|
"author": "Christophe CAMENSULI <ccamensuli@gmail.com>",
|
|
6
6
|
"type": "module",
|
|
@@ -36,28 +36,28 @@
|
|
|
36
36
|
"esm"
|
|
37
37
|
],
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@nodefony/framework": "^10.0.0-alpha.
|
|
40
|
-
"@nodefony/http": "^10.0.0-alpha.
|
|
41
|
-
"nodefony": "^10.0.0-alpha.
|
|
42
|
-
"zod": "^4.
|
|
39
|
+
"@nodefony/framework": "^10.0.0-alpha.5",
|
|
40
|
+
"@nodefony/http": "^10.0.0-alpha.5",
|
|
41
|
+
"nodefony": "^10.0.0-alpha.5",
|
|
42
|
+
"zod": "^4.6.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@nodefony/framework": "^10.0.0-alpha.
|
|
46
|
-
"@nodefony/http": "^10.0.0-alpha.
|
|
45
|
+
"@nodefony/framework": "^10.0.0-alpha.5",
|
|
46
|
+
"@nodefony/http": "^10.0.0-alpha.5",
|
|
47
47
|
"@types/chai": "5.2.3",
|
|
48
|
-
"@types/node": "26.
|
|
48
|
+
"@types/node": "26.5.1",
|
|
49
49
|
"@vitest/coverage-v8": "5.0.0",
|
|
50
50
|
"chai": "6.2.2",
|
|
51
|
-
"nodefony": "^10.0.0-alpha.
|
|
51
|
+
"nodefony": "^10.0.0-alpha.5",
|
|
52
52
|
"rimraf": "6.1.3",
|
|
53
|
-
"vite": "8.
|
|
53
|
+
"vite": "8.3.0",
|
|
54
54
|
"vitest": "5.0.0"
|
|
55
55
|
},
|
|
56
56
|
"private": false,
|
|
57
57
|
"engines": {
|
|
58
58
|
"node": ">=24.0.0"
|
|
59
59
|
},
|
|
60
|
-
"license": "
|
|
60
|
+
"license": "Apache-2.0",
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"tslib": "2.8.1"
|
|
63
63
|
},
|