@starterlib/cli 0.10.7 → 0.10.9

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,17 +31,17 @@ 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` ; `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`) |
44
+ | `starter-web etapes` | Liste les etapes et les roles qu'elles concernent |
45
45
 
46
46
  Codes de sortie : `0` conforme ; `1` une etape a echoue ; `2` la commande ne peut pas s'executer
47
47
  (argument inconnu, projet illisible).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@starterlib/cli",
3
- "version": "0.10.7",
3
+ "version": "0.10.9",
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",
@@ -27,11 +27,21 @@
27
27
  * morceau d'une construction precedente) est retiree, et une variante devenue inutile aussi :
28
28
  * le serveur servirait sinon un contenu que plus rien ne produit.
29
29
  *
30
+ * LE CONDENSE DE CHAQUE SOURCE (lot 120)
31
+ *
32
+ * Dans l'image, Jib fige toutes les dates : le serveur ne peut pas voir qu'une variante vient
33
+ * d'une construction precedente (une copie sans purge garde l'ancien `remoteEntry.json.gz` quand
34
+ * la nouvelle construction n'ecrit plus que le `.br`). L'etape ecrit donc `precompression.index`
35
+ * a la racine du dossier : une ligne par VARIANTE ecrite, le condense de son SOURCE (SHA-256
36
+ * tronque a 128 bits, comme l'ETag du serveur), deux blancs, le chemin de la variante.
37
+ * `ActifsStatiques` ne sert une variante que si l'index la nomme avec le condense de son source.
38
+ *
30
39
  * L'etape vient APRES la generation du manifeste, qui renomme les catalogues i18n.
31
40
  */
32
41
  import { brotliCompressSync, constants, gzipSync } from 'node:zlib';
42
+ import { createHash } from 'node:crypto';
33
43
  import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
34
- import { extname } from 'node:path';
44
+ import { extname, join } from 'node:path';
35
45
  import { fichiers, ko, relatif } from '../commun.mjs';
36
46
 
37
47
  /** Exactement ce que le serveur declare compressible (ActifsStatiques.EXTENSIONS_COMPRESSIBLES). */
@@ -48,6 +58,14 @@ export const COMPRESSIBLES = new Set([
48
58
  /** Reecrit a chaque reponse par le serveur : une variante figee serait fausse. */
49
59
  const EXCLUS = new Set(['index.html']);
50
60
 
61
+ /** L'index des variantes, lu par `ActifsStatiques.INDEX_DES_VARIANTES`. */
62
+ export const INDEX_DES_VARIANTES = 'precompression.index';
63
+
64
+ /** Le condense d'un contenu tel que le serveur le calcule : SHA-256 tronque a 128 bits, en hexadecimal. */
65
+ export function condense(contenu) {
66
+ return createHash('sha256').update(contenu).digest('hex').slice(0, 32);
67
+ }
68
+
51
69
  /**
52
70
  * Precompresse `dossier`. Rend `{ compresses, orphelines, octetsAvant, octetsBrotli, sansVariante }`,
53
71
  * `sansVariante` listant les `.js` qui devraient avoir une variante brotli et n'en ont pas.
@@ -69,6 +87,7 @@ export function precompresser(dossier) {
69
87
  let octetsAvant = 0;
70
88
  let octetsBrotli = 0;
71
89
  const sansGain = new Set();
90
+ const index = [];
72
91
  for (const fichier of fichiers(dossier)) {
73
92
  const extension = extname(fichier);
74
93
  if (extension === '.br' || extension === '.gz') continue;
@@ -88,6 +107,7 @@ export function precompresser(dossier) {
88
107
  ]) {
89
108
  if (compresse.length < contenu.length) {
90
109
  writeFileSync(variante, compresse);
110
+ index.push(`${condense(contenu)} ${relatif(dossier, variante)}`);
91
111
  ecrit = true;
92
112
  } else {
93
113
  // Une variante d'une passe precedente, devenue plus lourde que l'original : retiree.
@@ -102,12 +122,18 @@ export function precompresser(dossier) {
102
122
  sansGain.add(fichier);
103
123
  }
104
124
  }
125
+ const cheminDeLIndex = join(dossier, INDEX_DES_VARIANTES);
126
+ if (index.length > 0) {
127
+ writeFileSync(cheminDeLIndex, `${index.sort().join('\n')}\n`);
128
+ } else {
129
+ rmSync(cheminDeLIndex, { force: true });
130
+ }
105
131
 
106
132
  const sansVariante = fichiers(dossier)
107
133
  .filter((fichier) => extname(fichier) === '.js' && !sansGain.has(fichier))
108
134
  .filter((fichier) => !existsSync(`${fichier}.br`))
109
135
  .map((fichier) => relatif(dossier, fichier));
110
- return { compresses, orphelines, octetsAvant, octetsBrotli, sansVariante };
136
+ return { compresses, orphelines, octetsAvant, octetsBrotli, sansVariante, indexes: index.length };
111
137
  }
112
138
 
113
139
  /** Le compte rendu d'une precompression, et ses defauts (une etape devenue inutile en est un). */