@starterlib/cli 0.10.13 → 0.11.0

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 CHANGED
@@ -31,42 +31,45 @@ Scripts d'une SPA :
31
31
 
32
32
  ## Commandes
33
33
 
34
- | Commande | Ce qu'elle fait |
35
- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
36
- | `starter-web start` | L'hote de developpement : sprite, simulations (remote), puis `ng serve` sous `STARTER_WEB_HOTE_DEV=1` (`--port N`) |
37
- | `starter-web verify` | Les etapes ci-dessous, dans l'ordre, arretees a la premiere qui echoue, dont le nom est ecrit |
38
- | `starter-web construire` | Sprite, `ng build`, prechargement de la police (hote), manifeste, precompression |
39
- | `starter-web sprite` | Pose le sprite hache (`public/`) et sa constante engendree (`sprite-genere.ts`) |
40
- | `starter-web manifeste` | Engendre `manifest.json` dans le dossier livre ; idempotent |
41
- | `starter-web precompresser` | Ecrit les variantes `.br` et `.gz`, et `precompression.index` (chaque variante et le condense de son source, que le serveur confronte) ; `starter-web precompresser <dossier>` pour un autre dossier |
42
- | `starter-web i18n:types` | Engendre `src/app/i18n/cles.ts`, le type des cles de chaque perimetre (`injecterTraduction<C>`) |
43
- | `starter-web simulations` | Recopie les stubs WireMock du service (`../src/mock`), corps compris, pour l'hote de developpement (`src/hote-dev/simulations.engendre.json`) |
44
- | `starter-web etapes` | Liste les etapes et les roles qu'elles concernent |
34
+ | Commande | Ce qu'elle fait |
35
+ | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
36
+ | `starter-web start` | L'hote de developpement : sprite, simulations (remote), puis `ng serve` sous `STARTER_WEB_HOTE_DEV=1` (`--port N`) |
37
+ | `starter-web verify` | Les etapes ci-dessous, dans l'ordre, arretees a la premiere qui echoue, dont le nom est ecrit |
38
+ | `starter-web construire` | Sprite, `ng build`, prechargement de la police (hote), manifeste, precompression |
39
+ | `starter-web sprite` | Pose le sprite hache (`public/`) et sa constante engendree (`sprite-genere.ts`) |
40
+ | `starter-web manifeste` | Engendre `manifest.json` dans le dossier livre ; idempotent |
41
+ | `starter-web precompresser` | Ecrit les variantes `.br` et `.gz`, et `precompression.index` (chaque variante et le condense de son source, que le serveur confronte) ; `starter-web precompresser <dossier>` pour un autre dossier |
42
+ | `starter-web i18n:types` | Engendre `src/app/i18n/cles.ts`, le type des cles de chaque perimetre (`injecterTraduction<C>`) |
43
+ | `starter-web simulations` | Recopie les stubs WireMock du service (`../src/mock`), corps compris, pour l'hote de developpement (`src/hote-dev/simulations.engendre.json`) ; `--scenarios` liste et juge les scenarios nommes du remote (`src/hote-dev/scenarios.json`), chacun avec son adresse `?scenario=<nom>` (P08-10) |
44
+ | `starter-web navigateurs` | Ecrit `.browserslistrc` : la liste browserslist du socle, tiree du plancher de la matrice (lot 276) |
45
+ | `starter-web etapes` | Liste les etapes et les roles qu'elles concernent |
45
46
 
46
47
  Codes de sortie : `0` conforme ; `1` une etape a echoue ; `2` la commande ne peut pas s'executer
47
48
  (argument inconnu, projet illisible).
48
49
 
49
50
  ## Les etapes de `verify`
50
51
 
51
- | Etape | Role | Ce qu'elle garde |
52
- | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
53
- | `versions` | les deux | Versions exactes de la matrice, greffon de federation lie a Angular, pnpm, Node, train du socle |
54
- | `dependances` | les deux | Dependances de production revues, paquets interdits, aucun outil du socle recopie sous `tools/` |
55
- | `jetons` | les deux | Chaque `var(--st-*)` sans repli existe dans `@starterlib/tokens` (feuilles et styles en ligne) |
56
- | `format` | les deux | `prettier --check .` |
57
- | `lint` | les deux | Prefixe des selecteurs (jamais `st-`), `eslint .`, puis stylelint (configuration du socle exigee) |
58
- | `i18n` | les deux | Memes cles et arguments en fr et en, messages lisibles, cles appelees presentes, aide de chaque page (`<perimetre>.aide.<page>`), types a jour |
59
- | `test` | les deux | `ng test --no-watch` |
60
- | `contrat` | les deux | `pnpm run contrat:check` s'il existe (client d'API engendre, lot 175), sinon sautee en le disant |
61
- | `simulations` | remote | Les stubs WireMock du service, tels que l'hote de developpement les rejoue, a jour (lot 269) ; sautee sans simulateur ; un stub hors du sous-ensemble est nomme |
62
- | `build` | les deux | `starter-web construire` |
63
- | `vulnerabilites` | les deux | `pnpm audit --prod` : HIGH et CRITICAL bloquent sauf exception DATEE de `securite/exceptions-npm.json` (un trimestre au plus) ; SBOM CycloneDX dans `dist/sbom-front.cdx.json`, a cote du dossier livre (jamais servie) ; licences AGPL, SSPL et inconnues refusees (lot 139) |
64
- | `manifeste` | les deux | `validerLeManifesteDeRemote` et le schema de `@starterlib/core` INSTALLE ; le nom partout le meme |
65
- | `federation` | les deux | Partage en singleton strict a plage explicite, Angular et le socle partages, aucun import nu orphelin |
66
- | `entree` | hote | Aucun paquet partage importe statiquement avant `initFederation` |
67
- | `budget` | les deux | En brotli. Remote : chaque page (60 Ko), le total (250 Ko), les catalogues. Hote : premier ecran |
68
- | `amorcage` | hote | Aucun pair lourd (CDK, aria, formulaires, surfaces) dans le premier ecran |
69
- | `securite` | les deux | Puits de l'ADR 0029 dans le code de la SPA, politiques Trusted Types exactes, cartes, SVG, meta CSP |
52
+ | Etape | Role | Ce qu'elle garde |
53
+ | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
+ | `versions` | tous | Versions exactes de la matrice, greffon de federation lie a Angular, pnpm, Node, train du socle |
55
+ | `navigateurs` | tous | La liste browserslist de la SPA (`.browserslistrc`, ou `browserslist` de `package.json`) est celle du plancher de la matrice : ni absente, ni plus basse, ni plus large (lot 276) |
56
+ | `dependances` | tous | Dependances de production revues, paquets interdits, aucun outil du socle recopie sous `tools/` |
57
+ | `jetons` | tous | Chaque `var(--st-*)` sans repli existe dans `@starterlib/tokens` (feuilles et styles en ligne) |
58
+ | `format` | tous | `prettier --check .` |
59
+ | `lint` | tous | Prefixe des selecteurs (jamais `st-`), `eslint .`, puis stylelint (configuration du socle exigee) |
60
+ | `i18n` | tous | Memes cles et arguments en fr et en, messages lisibles, cles appelees presentes, aide de chaque page (`<perimetre>.aide.<page>`), types a jour, formulations interdites par l'application (`starterWeb.formulationsInterdites`) |
61
+ | `test` | tous | `ng test --no-watch` |
62
+ | `contrat` | tous | `pnpm run contrat:check` s'il existe (client d'API engendre, lot 175), sinon sautee en le disant |
63
+ | `simulations` | remote | Les stubs WireMock du service, tels que l'hote de developpement les rejoue, a jour (lot 269) ; sautee sans simulateur ni scenarios ; un stub hors du sous-ensemble est nomme ; le fichier de scenarios, s'il existe, juge (P08-10 : un scenario que l'hote ne rejouerait pas est un defaut) |
64
+ | `build` | tous | `starter-web construire` |
65
+ | `vulnerabilites` | tous | `pnpm audit --prod` : HIGH et CRITICAL bloquent sauf exception DATEE de `securite/exceptions-npm.json` (un trimestre au plus) ; SBOM CycloneDX dans `dist/sbom-front.cdx.json`, a cote du dossier livre (jamais servie) ; licences AGPL, SSPL et inconnues refusees (lot 139) |
66
+ | `manifeste` | les deux | `validerLeManifesteDeRemote` et le schema de `@starterlib/core` INSTALLE ; le nom partout le meme |
67
+ | `federation` | les deux | Partage en singleton strict a plage explicite, Angular et le socle partages, aucun import nu orphelin |
68
+ | `entree` | hote | Aucun paquet partage importe statiquement avant `initFederation` |
69
+ | `budget` | les deux | En brotli. Remote : chaque page (60 Ko), le total (250 Ko), les catalogues. Hote : premier ecran |
70
+ | `autonome` | autonome | Aucune federation livree (`remoteEntry`, carte d'importation, `es-module-shims`) ; versions d'Angular et du socle egales a celles du jumeau (`starterWeb.jumeau`) ; poids de l'ecran (`starterWeb.ecran` : entree et seuil en Ko br), lu dans la carte de la construction (lot 240) |
71
+ | `amorcage` | hote | Aucun pair lourd (CDK, aria, formulaires, surfaces) dans le premier ecran |
72
+ | `securite` | tous | Puits de l'ADR 0029 dans le code de la SPA, politiques Trusted Types exactes, cartes, SVG, meta CSP |
70
73
 
71
74
  `--etapes a,b` n'en joue que certaines ; `--sauter a,b` en retire.
72
75
 
@@ -81,9 +84,22 @@ par un point d'entree vide dans la configuration `production`).
81
84
 
82
85
  ## Ce que le CLI lit, et d'ou
83
86
 
84
- - le role : `package.json#starterWeb.role` (`"hote"` pour la coquille), sinon `remote` des qu'un
85
- `manifest.source.json` existe ;
87
+ - le role : `package.json#starterWeb.role` (`"hote"` pour la coquille, `"autonome"` pour une
88
+ application servie seule, sans federation : l'ecran anonyme d'identity, lot 240), sinon `remote` des
89
+ qu'un `manifest.source.json` existe ;
90
+ - pour une application autonome, dans `starterWeb` : `nom` (le projet d'`angular.json`),
91
+ `i18n.perimetres` (ses catalogues), `jumeau` (le dossier du remote du meme service, dont elle
92
+ partage les versions) et `ecran` (`{ "entree": "src/app/pages/connexion.ts", "seuilKo": 155 }`) ;
93
+ `starter-web construire` n'y ecrit pas de manifeste, et pose `--stats-json` ; `securite` y
94
+ neutralise UNE lecture de cookie du cadre (`DomAdapter.getCookie`, dans `main` faute de morceau
95
+ partage), toute autre restant un defaut ;
86
96
  - le nom et `pleinePage` : `manifest.source.json` (un remote), `socle` pour l'hote ;
97
+ - les formulations que l'application interdit dans ses textes : `starterWeb.formulationsInterdites`,
98
+ chemin d'un fichier JSON relatif a sa racine, qui liste des `formulations` (un `id`, des `textes`
99
+ ou un `motif`, des `langues` au besoin) et des `exceptions` (une `formulation`, une `cle`, une
100
+ `raison`, une `date`) ; l'etape `i18n` y cherche chaque texte sans casse ni accents et en mots
101
+ entiers, chaque motif tel quel (format detaille : `src/etapes/formulations.mjs`). Sans reglage,
102
+ rien n'est cherche : le socle ne connait aucune formulation ;
87
103
  - le prefixe des selecteurs : `prefix` du projet d'`angular.json` (ou `starterWeb.prefixe`) ;
88
104
  - le dossier livre : `outputPath` de la cible `@angular/build:application`, plus `browser` ;
89
105
  - le train requis et le socle construit : `remoteEntry.json`, ce que la federation a reellement
@@ -1,6 +1,6 @@
1
1
  # Matrice de compatibilite du socle frontal
2
2
 
3
- Verifiee le 2026-09-26 contre le registre npm (lot 154). Toute montee de version se fait
3
+ Verifiee le 2026-10-07 contre le registre npm (montee au dernier correctif de la ligne 22.2 ; avant elle, lot 154). Toute montee de version se fait
4
4
  **ligne par ligne, dans le meme commit**, et `pnpm versions:check` echoue si le
5
5
  `package.json` s'en ecarte (version non exacte, autre que celle de la matrice, paquet Angular absent
6
6
  de la matrice, greffon de federation d'une autre majeure.mineure qu'Angular, autre pnpm, Node sous le
@@ -9,27 +9,30 @@ lit CE document, publie avec lui, et ses essais le comparent a la matrice de `ve
9
9
 
10
10
  ⚠️ **Trois jours d'anciennete au moins** : `minimumReleaseAge: 4320` (`pnpm-workspace.yaml`) tient hors
11
11
  du verrou toute version publiee depuis moins de trois jours (constat A1405). Une version plus recente,
12
- meme corrective, attend : `@angular-architects/native-federation` 22.2.1 (publie le 2026-09-25) n'entre
13
- pas au 2026-09-27 ; la 22.2.0 (2026-09-24) y entre. Angular monte en 22.2.0 le 2026-09-27 (demande du
14
- proprietaire du 2026-09-26).
12
+ meme corrective, attend : au 2026-10-07, `axe-core` 4.14.0 (2026-10-05), `typescript-eslint` 8.71.1
13
+ (2026-10-05), `jsdom` 30.1.2 (2026-10-04), `@microsoft/api-extractor` 7.59.4 (2026-10-06) et `orval`
14
+ 8.40.0 (2026-10-04) n'entrent pas ; la version precedente de chacun y entre. Angular monte en 22.2.1 le
15
+ 2026-10-07 (correctif publie le 2026-09-30), apres la 22.2.0 du 2026-09-27.
15
16
 
16
17
  ## Train `2026.1`
17
18
 
18
19
  | Element | Version | Pourquoi cette version exactement |
19
20
  | -------------------------------------------------------------------------------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
20
- | `@angular/core`, `common`, `compiler`, `compiler-cli`, `forms`, `platform-browser`, `router` | `22.2.0` | Premiere de la ligne 22.2, publiee le 2026-09-23 (plus de trois jours au 2026-09-27) |
21
- | `@angular/cdk`, `aria` | `22.2.0` | Le paquet `aria` est stable depuis la 22 ; il porte les primitives sans style. `@angular/material` est retire : aucun composant du socle ne l'importe |
22
- | `@angular/build`, `@angular/cli` | `22.2.0` | ⚠️ **Cadence differente de `core`.** L'outillage recoit des correctifs que le coeur ne recoit pas. Une matrice qui ne porterait qu'un seul numero mentirait des le premier correctif |
23
- | `ng-packagr` | `22.2.1` | Derniere stable de la ligne 22.2 (2026-09-23) |
24
- | `typescript` | `6.0.3` | ⚠️ **Piege.** La 7.0.2 est publiee, mais `@angular/compiler-cli@22.2.0` exige `>=6.0 <6.1`. Installer la derniere casse la compilation |
21
+ | `@angular/core`, `common`, `compiler`, `compiler-cli`, `forms`, `platform-browser`, `router` | `22.2.1` | Dernier correctif de la ligne 22.2, publie le 2026-09-30 (plus de trois jours au 2026-10-07) |
22
+ | `@angular/cdk`, `aria` | `22.2.1` | Le paquet `aria` est stable depuis la 22 ; il porte les primitives sans style. `@angular/material` est retire : aucun composant du socle ne l'importe |
23
+ | `@angular/elements` | `22.2.1` | Les custom elements de `@starterlib/elements` seulement (lot 299, decision du proprietaire du 2026-10-01) ; son pair exige le numero exact de `@angular/core`, d'ou le meme 22.2.1 |
24
+ | `@angular/build`, `@angular/cli` | `22.2.1` | ⚠️ **Cadence differente de `core`.** L'outillage recoit des correctifs que le coeur ne recoit pas. Une matrice qui ne porterait qu'un seul numero mentirait des le premier correctif |
25
+ | `@angular-devkit/schematics` | `22.2.1` | Le moteur des schematics du CLI d'Angular, au meme numero : `@starterlib/schematics` (lot 285) n'en importe rien a l'execution, ses essais le lancent (`SchematicTestRunner`) |
26
+ | `ng-packagr` | `22.2.4` | Derniere stable de la ligne 22.2 (2026-10-01) |
27
+ | `typescript` | `6.0.3` | ⚠️ **Piege.** La 7.0.2 est publiee, mais `@angular/compiler-cli@22.2.1` exige `>=6.0 <6.1`. Installer la derniere casse la compilation |
25
28
  | `node` | `>=24.15.0` | 24.x LTS, declare dans `engines` ; le meme plancher que la construction Maven des SPA (`frontend.node.version`) |
26
29
  | `pnpm` | `11.27.1` | Declare dans `packageManager` ; reglages dans `pnpm-workspace.yaml` (`allowBuilds`, `minimumReleaseAge`). Le meme pour la construction Maven des SPA (`frontend.pnpm.version` de `platform-parent`) |
27
- | `vitest`, `@vitest/browser`, `@vitest/browser-playwright`, `@vitest/coverage-v8` | `5.0.1` | Lanceur officiel du constructeur `@angular/build:unit-test` ; un meme numero pour toute la famille (des numeros meles chargent deux copies du lanceur) |
30
+ | `vitest`, `@vitest/browser`, `@vitest/browser-playwright`, `@vitest/coverage-v8` | `5.0.3` | Lanceur officiel du constructeur `@angular/build:unit-test` ; un meme numero pour toute la famille (des numeros meles chargent deux copies du lanceur) |
28
31
  | `playwright`, `@playwright/test` | `1.63.0` | Le navigateur des essais : un correctif change un rendu mesure au pixel |
29
- | `eslint` | `10.10.0` | `angular-eslint@22.5.0` accepte les majeurs 9 et 10 |
32
+ | `eslint` | `10.12.0` | `angular-eslint@22.5.0` accepte les majeurs 9 et 10 |
30
33
  | `angular-eslint` | `22.5.0` | Suit le majeur d'Angular |
31
- | `stylelint`, `postcss-scss` | `17.15.0`, `4.0.9` | Les feuilles du socle et des SPA (lot 178, `@starterlib/eslint-config/stylelint`) ; `postcss-scss` lit le SCSS |
32
- | `jsdom`, `axe-core` | `30.0.1`, `4.13.0` | Le DOM des essais unitaires et le controle d'accessibilite : un correctif change ce qu'un essai voit |
34
+ | `stylelint`, `postcss-scss` | `17.16.0`, `4.0.9` | Les feuilles du socle et des SPA (lot 178, `@starterlib/eslint-config/stylelint`) ; `postcss-scss` lit le SCSS |
35
+ | `jsdom`, `axe-core` | `30.1.1`, `4.13.0` | Le DOM des essais unitaires et le controle d'accessibilite : un correctif change ce qu'un essai voit |
33
36
 
34
37
  ## Prochain train : `2026.2` (prevu, non applique)
35
38
 
@@ -47,8 +50,8 @@ interfaces), avec `pnpm verify` et `banc-d-assemblage.sh --construire` verts :
47
50
 
48
51
  | Element | Version | Avertissement |
49
52
  | --------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
50
- | `@angular-architects/native-federation` | `22.2.0` | ⚠️ **A epingler a l'exact, jamais par etiquette.** Le 2026-09-12, l'etiquette `latest` du paquet pointait sur la **21.2.6**, publiee apres la 22.1.2. Un `pnpm add` sans version ramene donc un majeur de retard, en silence, et l'echec se manifeste au chargement d'un remote, loin de la cause. Version mesuree au spike du 2026-09-16. Sa majeure.mineure est celle d'Angular (22.2) : `versions:check` refuse un couple disjoint, et les deux montent dans le meme commit (235a) |
51
- | `orval` | `8.37.0` | Client d'API engendre depuis le contrat du service (ADR web 0008) : services `HttpClient` pour les ecritures, `httpResource` pour les lectures, aucun schema zod, donc aucune dependance a l'execution. Derniere stable au 2026-09-25 ; a epingler a l'exact, en dependance de developpement |
53
+ | `@angular-architects/native-federation` | `22.2.2` | ⚠️ **A epingler a l'exact, jamais par etiquette.** Le 2026-09-12, l'etiquette `latest` du paquet pointait sur la **21.2.6**, publiee apres la 22.1.2. Un `pnpm add` sans version ramene donc un majeur de retard, en silence, et l'echec se manifeste au chargement d'un remote, loin de la cause. Version mesuree au spike du 2026-09-16. Sa majeure.mineure est celle d'Angular (22.2) : `versions:check` refuse un couple disjoint, et les deux montent dans le meme commit (235a) |
54
+ | `orval` | `8.39.0` | Client d'API engendre depuis le contrat du service (ADR web 0008) : services `HttpClient` pour les ecritures, `httpResource` pour les lectures, aucun schema zod, donc aucune dependance a l'execution. Derniere stable de plus de trois jours au 2026-10-07 (8.39.0, publiee le 2026-09-30) ; a epingler a l'exact, en dependance de developpement |
52
55
  | `es-module-shims` | `2.8.4` | Dependance du greffon, et pas un detail : c'est ELLE qui cree la politique de types de confiance `es-module-shims`. Toute montee doit verifier que le nom de la politique n'a pas change, sinon la page devient blanche sans erreur serveur |
53
56
  | `@axe-core/playwright` | `4.13.0` | Les essais d'accessibilite de bout en bout de la coquille (Playwright) ; le meme numero qu'`axe-core`, qui fait le controle : deux moteurs d'une version differente ne signaleraient pas les memes violations |
54
57
 
@@ -67,19 +70,31 @@ maximum, fonction par fonction, de ce que les feuilles et le noyau emploient san
67
70
  Sous ce plancher, rien ne casse sans le dire : une surface sans `@starting-style` apparait d'un coup ; une
68
71
  couleur sans `light-dark()` n'existe pas, d'ou le plancher.
69
72
 
73
+ Au-dessus du plancher, AVEC repli (P08-03) : la requete de style d'une propriete personnalisee,
74
+ `@container style(--st-prefixe-de-ton: visible)` (Chrome 111, Safari 18, Firefox 151), affiche le prefixe
75
+ de ton (« Erreur : ») qu'une application demande visible ; en deca, il reste masque, et toujours lu.
76
+
70
77
  Ce plancher est plus haut que celui d'Angular 22.2 (« baseline widely available » au 2026-05-07 : Chrome et
71
78
  Edge 119, Firefox 119, Safari et iOS 17) : la construction ne vise pas plus bas que le socle n'en a besoin.
72
79
 
80
+ **Liste partagee (lot 276, 0.10.14).** La liste browserslist de chaque SPA DERIVE de la ligne du plancher
81
+ ci-dessus, que `@starterlib/cli` lit dans ce document publie avec lui : Chrome, Edge, Chrome Android et la
82
+ WebView d'Android au plancher de Chrome, Firefox et Firefox Android a celui de Firefox, Safari et iOS a
83
+ celui de Safari. `starter-web navigateurs` l'ecrit dans `.browserslistrc` ; l'etape `navigateurs` de
84
+ `starter-web verify` refuse une liste absente, plus basse ou plus large. Sous le plancher, l'hote montre
85
+ la page « navigateur non pris en charge » de `@starterlib/core/navigateur` au lieu de demarrer
86
+ (detection par fonction, jamais par l'agent utilisateur).
87
+
73
88
  **Mesure (banc d'assemblage du BFF, lot 276, 2026-10-01).** Playwright 1.63 : Chromium 153, Firefox 155,
74
89
  WebKit 26.6, Pixel 7 et iPhone 15 emules. Chromium et le telephone Android jouent tout le banc a chaque
75
90
  poussee ; Firefox, WebKit et l'iPhone jouent les scenarios `@moteurs` et `@mobile` chaque semaine
76
91
  (`BANC_MOTEURS=tous`).
77
92
 
78
- | Moteur | Version mesuree | Plancher | Ce qui se degrade entre le plancher et la mesure |
79
- | ------------- | --------------- | -------- | ---------------------------------------------------------------------------------- |
80
- | Chromium/Edge | 153 | 123 | rien de connu : les types de confiance y sont appliques depuis bien avant 123 |
81
- | Firefox | 155 | 129 | la protection des puits DOM par les types de confiance, si la version ne les a pas |
82
- | Safari/iOS | 26.6 | 17.5 | idem ; la politique bloque toujours les scripts sans nonce |
93
+ | Moteur | Version mesuree | Plancher | Ce qui se degrade entre le plancher et la mesure |
94
+ | ------------- | --------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
95
+ | Chromium/Edge | 153 | 123 | rien de connu : les types de confiance y sont appliques depuis bien avant 123 |
96
+ | Firefox | 155 | 129 | la protection des puits DOM par les types de confiance, si la version ne les a pas ; avant 151, le prefixe de ton reste masque sous `--st-prefixe-de-ton: visible` |
97
+ | Safari/iOS | 26.6 | 17.5 | idem ; la politique bloque toujours les scripts sans nonce ; avant 18, le prefixe de ton reste masque |
83
98
 
84
99
  **WebView.** Android System WebView suit Chromium, WKWebView suit le Safari du systeme : memes planchers
85
100
  (decisions mobiles, ADR 0043 du socle `api/starter`). **Revision** : a chaque montee de Playwright (nouveaux moteurs) et au plus
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@starterlib/cli",
3
- "version": "0.10.13",
3
+ "version": "0.11.0",
4
4
  "description": "Chaine de verification et de construction des SPA du socle frontal starter : starter-web verify, construire, sprite, manifeste, precompresser. Jamais en dependance de production.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -50,21 +50,28 @@ export function construire(
50
50
  { configuration = 'production', journal = console, sprite = true } = {},
51
51
  ) {
52
52
  if (sprite) journal.info(` sprite : ${poserLeSprite(projet)}`);
53
+ // Une application autonome ecrit la carte de sa construction : l'etape `autonome` y lit le
54
+ // morceau de la route de son ecran (lot 240).
55
+ const carte = projet.role === 'autonome' ? ['--stats-json'] : [];
53
56
  const code = executer(
54
57
  'pnpm',
55
- ['exec', 'ng', 'build', '--configuration', configuration],
58
+ ['exec', 'ng', 'build', '--configuration', configuration, ...carte],
56
59
  projet.racine,
57
60
  );
58
61
  if (code !== 0) {
59
62
  journal.erreur(` ng build --configuration ${configuration} : code ${String(code)}.`);
60
63
  return code;
61
64
  }
62
- if (projet.role === 'hote')
65
+ // L'hote et l'application autonome peignent un premier ecran : la police s'y precharge.
66
+ if (projet.role === 'hote' || projet.role === 'autonome')
63
67
  journal.info(` police prechargee : ${prechargerLaPolice(projet.sortie)}`);
64
- const manifeste = ecrireLeManifeste(projet);
65
- journal.info(
66
- ` manifest.json : ${manifeste.nom} ${manifeste.version}, socle ${manifeste.socle.construit}`,
67
- );
68
+ // Une application autonome n'est pas assemblee : aucun manifeste (lot 240).
69
+ if (projet.role !== 'autonome') {
70
+ const manifeste = ecrireLeManifeste(projet);
71
+ journal.info(
72
+ ` manifest.json : ${manifeste.nom} ${manifeste.version}, socle ${manifeste.socle.construit}`,
73
+ );
74
+ }
68
75
  const { resume, defauts } = juger(precompresser(projet.sortie));
69
76
  journal.info(` precompression : ${resume}`);
70
77
  for (const defaut of defauts) journal.erreur(` - ${defaut}`);
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Le fichier de scenarios d'un remote (P08-10) : `src/hote-dev/scenarios.json`, les etats nommes
3
+ * d'une page que l'hote de developpement ouvre par l'adresse (`?scenario=<nom>`,
4
+ * `@starterlib/testing/hote-dev`). `starter-web simulations --scenarios` les liste ; l'etape
5
+ * `simulations` de `verify` les juge.
6
+ *
7
+ * ```json
8
+ * {
9
+ * "scenarios": {
10
+ * "liste-vide": {
11
+ * "description": "Aucun element : l'etat vide de la liste",
12
+ * "stubs": [
13
+ * {
14
+ * "request": { "method": "GET", "urlPath": "/api/v1/elements" },
15
+ * "response": { "status": 200, "jsonBody": { "content": [], "nextCursor": null } }
16
+ * }
17
+ * ]
18
+ * },
19
+ * "gestionnaire": {
20
+ * "description": "Session d'un gestionnaire",
21
+ * "session": { "nomAffiche": "Gabriel Essai", "roles": ["GESTIONNAIRE"] }
22
+ * }
23
+ * }
24
+ * }
25
+ * ```
26
+ *
27
+ * Un scenario porte une `description`, et au besoin des `stubs` (le sous-ensemble de WireMock que
28
+ * l'hote rejoue, corps EN LIGNE : `jsonBody` ou `body`) et une `session` (ce qu'elle change de la
29
+ * session simulee). Tout ecart est un DEFAUT : un scenario ecrit pour l'hote doit s'y rejouer. Les
30
+ * noms et les donnees sont fictifs : aucune donnee personnelle reelle.
31
+ */
32
+ import { existsSync, readFileSync } from 'node:fs';
33
+ import { join } from 'node:path';
34
+ import { horsDuSousEnsemble } from './simulations.mjs';
35
+
36
+ /** Ou vit le fichier de scenarios, depuis la racine de la SPA. */
37
+ export const CHEMIN_DES_SCENARIOS = join('src', 'hote-dev', 'scenarios.json');
38
+
39
+ /** Le nom d'un scenario : celui qu'on tape dans l'adresse (`NOM_DE_SCENARIO` de l'hote). */
40
+ export const NOM_DE_SCENARIO = /^[a-z][a-z0-9-]{0,60}$/;
41
+
42
+ const CLES_DU_SCENARIO = new Set(['description', 'stubs', 'session']);
43
+
44
+ /** Ce que la session simulee d'un scenario peut changer (`ReponseDeSession` du noyau). */
45
+ const CLES_DE_SESSION = new Set([
46
+ 'authenticated',
47
+ 'userId',
48
+ 'csrfToken',
49
+ 'email',
50
+ 'nomAffiche',
51
+ 'langue',
52
+ 'theme',
53
+ 'roles',
54
+ 'permissionsAffichables',
55
+ 'mustChangePassword',
56
+ 'montantsMasques',
57
+ 'expiresAt',
58
+ 'absoluteExpiresAt',
59
+ ]);
60
+
61
+ const estUnObjet = (valeur) =>
62
+ typeof valeur === 'object' && valeur !== null && !Array.isArray(valeur);
63
+
64
+ /** Les defauts d'un scenario (vide : il se rejoue). */
65
+ function defautsDuScenario(nom, scenario) {
66
+ const defauts = [];
67
+ if (!NOM_DE_SCENARIO.test(nom)) {
68
+ defauts.push(`scenario "${nom}" : nom attendu en minuscules et tirets (^[a-z][a-z0-9-]*$).`);
69
+ }
70
+ if (!estUnObjet(scenario)) return [...defauts, `scenario "${nom}" : un objet est attendu.`];
71
+ for (const cle of Object.keys(scenario)) {
72
+ if (!CLES_DU_SCENARIO.has(cle)) defauts.push(`scenario "${nom}" : cle inconnue "${cle}".`);
73
+ }
74
+ if (typeof scenario.description !== 'string' || scenario.description.trim() === '') {
75
+ defauts.push(`scenario "${nom}" : description absente (ce que le scenario montre).`);
76
+ }
77
+ if (scenario.stubs !== undefined) {
78
+ if (!Array.isArray(scenario.stubs)) {
79
+ defauts.push(`scenario "${nom}" : stubs attendus en liste.`);
80
+ } else {
81
+ for (const [indice, stub] of scenario.stubs.entries()) {
82
+ const ou = `scenario "${nom}", stub ${String(indice)}`;
83
+ if (!estUnObjet(stub?.request) || !estUnObjet(stub?.response)) {
84
+ defauts.push(`${ou} : request et response attendus.`);
85
+ continue;
86
+ }
87
+ if (stub.response.bodyFileName !== undefined) {
88
+ defauts.push(`${ou} : corps en ligne attendu (jsonBody ou body), pas bodyFileName.`);
89
+ }
90
+ const raisons = horsDuSousEnsemble(stub);
91
+ if (raisons.length > 0) {
92
+ defauts.push(`${ou} : hors de ce que l'hote rejoue : ${raisons.join(', ')}.`);
93
+ }
94
+ }
95
+ }
96
+ }
97
+ if (scenario.session !== undefined) {
98
+ if (!estUnObjet(scenario.session)) {
99
+ defauts.push(`scenario "${nom}" : session attendue en objet.`);
100
+ } else {
101
+ for (const cle of Object.keys(scenario.session)) {
102
+ if (!CLES_DE_SESSION.has(cle)) {
103
+ defauts.push(`scenario "${nom}" : session, cle inconnue "${cle}".`);
104
+ }
105
+ }
106
+ }
107
+ }
108
+ return defauts;
109
+ }
110
+
111
+ /**
112
+ * Lit et juge le fichier de scenarios : `{ chemin, scenarios, defauts }`, chaque scenario
113
+ * `{ nom, description, stubs, session }` (nombre de stubs, session changee ou non), ou `null` si la
114
+ * SPA n'en a pas.
115
+ */
116
+ export function lireLesScenarios(projet) {
117
+ const chemin = join(projet.racine, CHEMIN_DES_SCENARIOS);
118
+ if (!existsSync(chemin)) return null;
119
+ let contenu;
120
+ try {
121
+ contenu = JSON.parse(readFileSync(chemin, 'utf8'));
122
+ } catch (erreur) {
123
+ return {
124
+ chemin,
125
+ scenarios: [],
126
+ defauts: [
127
+ `${CHEMIN_DES_SCENARIOS} illisible : ${erreur instanceof Error ? erreur.message : String(erreur)}.`,
128
+ ],
129
+ };
130
+ }
131
+ if (!estUnObjet(contenu) || !estUnObjet(contenu.scenarios)) {
132
+ return {
133
+ chemin,
134
+ scenarios: [],
135
+ defauts: [`${CHEMIN_DES_SCENARIOS} : un objet "scenarios" est attendu.`],
136
+ };
137
+ }
138
+ const defauts = [];
139
+ for (const cle of Object.keys(contenu)) {
140
+ if (cle !== 'scenarios' && cle !== '$comment') {
141
+ defauts.push(`${CHEMIN_DES_SCENARIOS} : cle inconnue "${cle}".`);
142
+ }
143
+ }
144
+ const scenarios = [];
145
+ for (const [nom, scenario] of Object.entries(contenu.scenarios)) {
146
+ defauts.push(...defautsDuScenario(nom, scenario));
147
+ scenarios.push({
148
+ nom,
149
+ description: typeof scenario?.description === 'string' ? scenario.description : '',
150
+ stubs: Array.isArray(scenario?.stubs) ? scenario.stubs.length : 0,
151
+ session: estUnObjet(scenario?.session),
152
+ });
153
+ }
154
+ return { chemin, scenarios, defauts };
155
+ }
@@ -110,8 +110,11 @@ export function racineDesStubs(projet) {
110
110
  return null;
111
111
  }
112
112
 
113
- /** Les raisons pour lesquelles l'hote ne rejouerait pas ce stub (vide : il le rejoue). */
114
- function horsDuSousEnsemble(stub) {
113
+ /**
114
+ * Les raisons pour lesquelles l'hote ne rejouerait pas ce stub (vide : il le rejoue). Le fichier de
115
+ * scenarios (P08-10) les tient pour des defauts.
116
+ */
117
+ export function horsDuSousEnsemble(stub) {
115
118
  const raisons = [];
116
119
  const inconnues = (objet, admises, ou) => {
117
120
  for (const cle of Object.keys(objet ?? {})) {
@@ -20,9 +20,14 @@ import { empreinteCourte } from '../commun.mjs';
20
20
 
21
21
  const SPRITE_HACHE = /^sprite-[A-Z0-9]{8}\.svg$/;
22
22
 
23
- /** Les chemins du sprite selon le role. */
23
+ /**
24
+ * Les chemins du sprite selon le role. Une application autonome (lot 240) peint le sprite du SOCLE,
25
+ * comme l'hote : elle n'a ni remote ni sprite metier.
26
+ */
27
+ const duSocle = (projet) => projet.role === 'hote' || projet.role === 'autonome';
28
+
24
29
  function reglages(projet) {
25
- if (projet.role === 'hote') {
30
+ if (duSocle(projet)) {
26
31
  return {
27
32
  source: join(
28
33
  projet.racine,
@@ -74,11 +79,11 @@ export function poserLeSprite(projet) {
74
79
  const { source, dossier, adresse, genere, constante } = reglages(projet);
75
80
  if (!existsSync(source)) {
76
81
  throw new Error(
77
- `sprite absent : ${source}${projet.role === 'hote' ? " (pnpm install d'abord)" : ''}.`,
82
+ `sprite absent : ${source}${duSocle(projet) ? " (pnpm install d'abord)" : ''}.`,
78
83
  );
79
84
  }
80
85
  const contenu = readFileSync(source);
81
- if (projet.role === 'hote') verifierLeSpriteDuSocle(source, contenu);
86
+ if (duSocle(projet)) verifierLeSpriteDuSocle(source, contenu);
82
87
  const fichier = `sprite-${empreinteCourte(contenu)}.svg`;
83
88
  mkdirSync(dossier, { recursive: true });
84
89
  for (const existant of readdirSync(dossier)) {