@starterlib/cli 0.14.0 → 0.15.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 +8 -0
- package/package.json +1 -1
- package/src/construction/construire.mjs +10 -1
- package/src/construction/service-worker/hors-ligne.css +42 -0
- package/src/construction/service-worker/hors-ligne.html +34 -0
- package/src/construction/service-worker/sw-retrait.js +22 -0
- package/src/construction/service-worker/sw.js +81 -0
- package/src/construction/service-worker.mjs +77 -0
- package/src/etapes/securite.mjs +18 -12
- package/src/projet.mjs +10 -0
package/README.md
CHANGED
|
@@ -104,6 +104,14 @@ par un point d'entree vide dans la configuration `production`).
|
|
|
104
104
|
`["src/app/gabarits/coquille.ts", "src/app/pages/accueil.ts"]`), cherchees dans `browser-stats.json` que la
|
|
105
105
|
cible esbuild d'`angular.json` ecrit avec `statsJson: true` ; sans elles, le premier ecran compte toutes les pages
|
|
106
106
|
de route (D171) ;
|
|
107
|
+
- pour l'hote seul (0.15.0, lot P09-49 d'Aplomb), `starterWeb.serviceWorker: true` : `starter-web construire` pose a
|
|
108
|
+
la racine de sa sortie `sw.js` (une navigation que le reseau ne sert pas recoit la page hors ligne ; aucune page,
|
|
109
|
+
aucune reponse d'API ni du BFF, aucun manifeste en cache, aucune file hors ligne ; sa version est le condense de la
|
|
110
|
+
page construite), `sw-retrait.js` (l'interrupteur de retrait, que le serveur sert sous `/sw.js` a sa place), et la
|
|
111
|
+
page hors ligne `hors-ligne.html` avec sa feuille `hors-ligne.css`, statiques, que l'application remplace en posant
|
|
112
|
+
les siennes dans `public/` (`src/construction/service-worker.mjs`). Le serveur sert `/sw.js` sans cache et admet
|
|
113
|
+
`worker-src 'self'` ; l'hote l'enregistre par `enregistrerLeServiceWorker` (`@starterlib/core/navigateur`), sous la
|
|
114
|
+
politique Trusted Types `starter#service-worker`. Refuse pour un remote ou une application autonome ;
|
|
107
115
|
- le nom et `pleinePage` : `manifest.source.json` (un remote), `socle` pour l'hote ;
|
|
108
116
|
- les formulations que l'application interdit dans ses textes : `starterWeb.formulationsInterdites`,
|
|
109
117
|
chemin d'un fichier JSON relatif a sa racine, qui liste des `formulations` (un `id`, des `textes`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starterlib/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.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",
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* PRERENDUE (`starterWeb.prerendu`, 0.11.4) le pose dans chaque page, et sort de ses pages les feuilles des
|
|
8
8
|
* composants et les attributs `style` (`prerendu.mjs`) ;
|
|
9
9
|
* 4. le manifeste (il renomme les catalogues i18n) ;
|
|
10
|
-
* 5.
|
|
10
|
+
* 5. le service worker minimal d'un hote qui le demande (`starterWeb.serviceWorker`, P09-49 d'Aplomb) : sa version
|
|
11
|
+
* est le condense de la page definitive ;
|
|
12
|
+
* 6. la precompression (apres le renommage, sans quoi des variantes resteraient orphelines).
|
|
11
13
|
*/
|
|
12
14
|
import { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
13
15
|
import { join } from 'node:path';
|
|
@@ -19,6 +21,7 @@ import {
|
|
|
19
21
|
prechargerLaPoliceDansLesPages,
|
|
20
22
|
resumerLExternalisation,
|
|
21
23
|
} from './prerendu.mjs';
|
|
24
|
+
import { poserLeServiceWorker } from './service-worker.mjs';
|
|
22
25
|
import { poserLeSprite } from './sprite.mjs';
|
|
23
26
|
|
|
24
27
|
/** Inter latin, graisse variable, style normal : le nom que `polices.css` du socle donne. */
|
|
@@ -100,6 +103,12 @@ export function construire(
|
|
|
100
103
|
` manifest.json : ${manifeste.nom} ${manifeste.version}, socle ${manifeste.socle.construit}`,
|
|
101
104
|
);
|
|
102
105
|
}
|
|
106
|
+
// Le service worker minimal d'un hote qui le demande (P09-49) : apres la page definitive, avant la precompression.
|
|
107
|
+
if (projet.serviceWorker) {
|
|
108
|
+
const { version, gardes } = poserLeServiceWorker(projet.sortie);
|
|
109
|
+
const propres = gardes.length === 0 ? '' : ` ; de l'application : ${gardes.join(', ')}`;
|
|
110
|
+
journal.info(` service worker : sw.js ${version}, sw-retrait.js, page hors ligne${propres}`);
|
|
111
|
+
}
|
|
103
112
|
const { resume, defauts } = juger(precompresser(projet.sortie));
|
|
104
113
|
journal.info(` precompression : ${resume}`);
|
|
105
114
|
for (const defaut of defauts) journal.erreur(` - ${defaut}`);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Feuille de la page hors ligne du socle frontal (lot P09-49 d'Aplomb) : gardee par le service worker avec sa page, sans
|
|
3
|
+
* police ni image a charger (le reseau manque). Les deux themes suivent le systeme.
|
|
4
|
+
*/
|
|
5
|
+
:root {
|
|
6
|
+
color-scheme: light dark;
|
|
7
|
+
font-family:
|
|
8
|
+
system-ui,
|
|
9
|
+
-apple-system,
|
|
10
|
+
'Segoe UI',
|
|
11
|
+
Roboto,
|
|
12
|
+
sans-serif;
|
|
13
|
+
line-height: 1.5;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
margin: 0;
|
|
18
|
+
background: Canvas;
|
|
19
|
+
color: CanvasText;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.hors-ligne {
|
|
23
|
+
box-sizing: border-box;
|
|
24
|
+
max-inline-size: 36rem;
|
|
25
|
+
margin-inline: auto;
|
|
26
|
+
padding-block: 4rem;
|
|
27
|
+
padding-inline: 1rem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
h1 {
|
|
31
|
+
font-size: 1.5rem;
|
|
32
|
+
line-height: 1.25;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
h2 {
|
|
36
|
+
font-size: 1.125rem;
|
|
37
|
+
line-height: 1.3;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
a {
|
|
41
|
+
color: LinkText;
|
|
42
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<!--
|
|
3
|
+
Page hors ligne du socle frontal (@starterlib ; lot P09-49 d'Aplomb) : le service worker la rend a une navigation que
|
|
4
|
+
le reseau ne sert pas. Statique : aucun script, aucun style en ligne (la politique de la page n'en admet pas sans
|
|
5
|
+
nonce), aucune donnee. Une application la remplace par la sienne en posant `hors-ligne.html` et `hors-ligne.css`
|
|
6
|
+
dans `public/`.
|
|
7
|
+
-->
|
|
8
|
+
<html lang="fr">
|
|
9
|
+
<head>
|
|
10
|
+
<meta charset="utf-8" />
|
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
+
<title>Hors ligne · Offline</title>
|
|
13
|
+
<link rel="stylesheet" href="/hors-ligne.css" />
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<main class="hors-ligne">
|
|
17
|
+
<h1>Vous êtes hors ligne</h1>
|
|
18
|
+
<p>
|
|
19
|
+
La page demandée n’a pas pu se charger. Rien n’a été
|
|
20
|
+
envoyé. Vérifiez votre connexion, puis rechargez la page.
|
|
21
|
+
</p>
|
|
22
|
+
<div lang="en">
|
|
23
|
+
<h2>You are offline</h2>
|
|
24
|
+
<p>
|
|
25
|
+
The page could not load, and nothing was sent. Check your connection, then reload the
|
|
26
|
+
page.
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
<p>
|
|
30
|
+
<a href="">Recharger la page · <span lang="en">Reload the page</span></a>
|
|
31
|
+
</p>
|
|
32
|
+
</main>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Interrupteur de retrait du service worker du socle frontal (@starterlib ; lot P09-49 d'Aplomb) : le BFF le sert sous
|
|
3
|
+
* `/sw.js` a la place du service worker quand l'exploitant le retire. Le navigateur, qui revoit `/sw.js` a chaque
|
|
4
|
+
* navigation, l'installe a la place de l'ancien : il efface les caches que celui-ci avait poses, puis se desinscrit.
|
|
5
|
+
* Les pages ouvertes continuent sur le reseau ; rien n'est recharge de force, rien n'est garde.
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
self.addEventListener('install', () => {
|
|
10
|
+
self.skipWaiting();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
self.addEventListener('activate', (evenement) => {
|
|
14
|
+
evenement.waitUntil(
|
|
15
|
+
(async () => {
|
|
16
|
+
for (const cle of await caches.keys()) {
|
|
17
|
+
if (cle.startsWith('starter-hors-ligne-')) await caches.delete(cle);
|
|
18
|
+
}
|
|
19
|
+
await self.registration.unregister();
|
|
20
|
+
})(),
|
|
21
|
+
);
|
|
22
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Service worker minimal du socle frontal (@starterlib ; lot P09-49 d'Aplomb, ratification « pwa-legere » de DEC-062),
|
|
3
|
+
* pose par `starter-web construire` dans la sortie d'un hote qui le demande (`starterWeb.serviceWorker`).
|
|
4
|
+
*
|
|
5
|
+
* Ce qu'il fait, et rien d'autre : une NAVIGATION que le reseau ne sert pas recoit la page hors ligne statique.
|
|
6
|
+
*
|
|
7
|
+
* Ce qu'il ne fait jamais : garder une page, une reponse `/api/**` ou `/bff/**`, un `manifest.json` ou un
|
|
8
|
+
* `remoteEntry.json` ; mettre un geste en file pour plus tard. Chaque navigation va au reseau : le BFF rend la coquille
|
|
9
|
+
* avec le nonce de SA reponse, les versions et la maintenance restent les siennes. Les seuls fichiers gardes sont la
|
|
10
|
+
* page hors ligne et sa feuille, statiques, sans donnee de la personne.
|
|
11
|
+
*
|
|
12
|
+
* Le BFF le sert sous `/sw.js`, sans cache (`Cache-Control: no-cache`) ; son interrupteur de retrait sert a la place
|
|
13
|
+
* `sw-retrait.js`, qui le desinscrit de chaque navigateur a la verification suivante.
|
|
14
|
+
*/
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
/** La version de la construction, posee par `starter-web construire` : une construction nouvelle, un worker nouveau. */
|
|
18
|
+
const VERSION = '__VERSION__';
|
|
19
|
+
const CACHE = `starter-hors-ligne-${VERSION}`;
|
|
20
|
+
const PAGE_HORS_LIGNE = '/hors-ligne.html';
|
|
21
|
+
const FEUILLE_HORS_LIGNE = '/hors-ligne.css';
|
|
22
|
+
|
|
23
|
+
self.addEventListener('install', (evenement) => {
|
|
24
|
+
evenement.waitUntil(
|
|
25
|
+
caches
|
|
26
|
+
.open(CACHE)
|
|
27
|
+
.then((cache) =>
|
|
28
|
+
cache.addAll(
|
|
29
|
+
[PAGE_HORS_LIGNE, FEUILLE_HORS_LIGNE].map(
|
|
30
|
+
(chemin) => new Request(chemin, { cache: 'reload' }),
|
|
31
|
+
),
|
|
32
|
+
),
|
|
33
|
+
)
|
|
34
|
+
.then(() => self.skipWaiting()),
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
self.addEventListener('activate', (evenement) => {
|
|
39
|
+
evenement.waitUntil(
|
|
40
|
+
(async () => {
|
|
41
|
+
// Les caches d'une version precedente partent : un seul jeu de fichiers hors ligne a la fois.
|
|
42
|
+
for (const cle of await caches.keys()) {
|
|
43
|
+
if (cle.startsWith('starter-hors-ligne-') && cle !== CACHE) await caches.delete(cle);
|
|
44
|
+
}
|
|
45
|
+
if (self.registration.navigationPreload) await self.registration.navigationPreload.enable();
|
|
46
|
+
await self.clients.claim();
|
|
47
|
+
})(),
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
self.addEventListener('fetch', (evenement) => {
|
|
52
|
+
const requete = evenement.request;
|
|
53
|
+
const adresse = new URL(requete.url);
|
|
54
|
+
// Une autre origine, une autre methode : le navigateur seul, comme sans service worker.
|
|
55
|
+
if (adresse.origin !== self.location.origin || requete.method !== 'GET') return;
|
|
56
|
+
|
|
57
|
+
if (requete.mode === 'navigate') {
|
|
58
|
+
evenement.respondWith(
|
|
59
|
+
(async () => {
|
|
60
|
+
try {
|
|
61
|
+
// Le prechargement de la navigation, s'il a eu lieu, sinon le reseau : jamais une copie.
|
|
62
|
+
const prechargee = await evenement.preloadResponse;
|
|
63
|
+
return prechargee ?? (await fetch(requete));
|
|
64
|
+
} catch {
|
|
65
|
+
return (await caches.match(PAGE_HORS_LIGNE, { cacheName: CACHE })) ?? Response.error();
|
|
66
|
+
}
|
|
67
|
+
})(),
|
|
68
|
+
);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// La feuille de la page hors ligne, et elle seule : lue au cache quand le reseau manque.
|
|
73
|
+
if (adresse.pathname === FEUILLE_HORS_LIGNE) {
|
|
74
|
+
evenement.respondWith(
|
|
75
|
+
fetch(requete).catch(
|
|
76
|
+
async () =>
|
|
77
|
+
(await caches.match(FEUILLE_HORS_LIGNE, { cacheName: CACHE })) ?? Response.error(),
|
|
78
|
+
),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Le service worker minimal d'un hote (lot P09-49 d'Aplomb ; ratification « pwa-legere » de DEC-062), pose dans sa
|
|
3
|
+
* sortie par `starter-web construire` quand `starterWeb.serviceWorker` le demande.
|
|
4
|
+
*
|
|
5
|
+
* - `sw.js` : une navigation que le reseau ne sert pas recoit la page hors ligne ; rien d'autre n'est garde ni rejoue
|
|
6
|
+
* (`service-worker/sw.js`). Sa VERSION est le condense de la page de la construction : une construction nouvelle
|
|
7
|
+
* change ses octets, et le navigateur installe le worker nouveau a la navigation suivante.
|
|
8
|
+
* - `sw-retrait.js` : l'interrupteur de retrait, que le BFF sert sous `/sw.js` a la place du worker.
|
|
9
|
+
* - `hors-ligne.html` et `hors-ligne.css` : la page hors ligne du socle, statique ; celle de l'application, posee dans
|
|
10
|
+
* `public/` (donc deja dans la sortie), est gardee.
|
|
11
|
+
*
|
|
12
|
+
* A poser APRES la page definitive (police prechargee) et AVANT la precompression, qui compresse aussi ces fichiers.
|
|
13
|
+
*/
|
|
14
|
+
import { createHash } from 'node:crypto';
|
|
15
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
|
|
19
|
+
const MODELES = fileURLToPath(new URL('./service-worker/', import.meta.url));
|
|
20
|
+
|
|
21
|
+
/** Les fichiers du service worker, a la racine de la sortie : le BFF les sert depuis la meme origine. */
|
|
22
|
+
export const FICHIERS_DU_SERVICE_WORKER = Object.freeze([
|
|
23
|
+
'sw.js',
|
|
24
|
+
'sw-retrait.js',
|
|
25
|
+
'hors-ligne.html',
|
|
26
|
+
'hors-ligne.css',
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* La politique Trusted Types de l'enregistrement, que `enregistrerLeServiceWorker` (`@starterlib/core/navigateur`)
|
|
31
|
+
* cree sous le meme nom : la politique de la page de l'hote doit la porter nommement.
|
|
32
|
+
*/
|
|
33
|
+
export const POLITIQUE_DU_SERVICE_WORKER = 'starter#service-worker';
|
|
34
|
+
|
|
35
|
+
/** Ce que l'application peut fournir a la place du socle : sa page hors ligne et sa feuille. */
|
|
36
|
+
const FOURNIS_PAR_L_APPLICATION = new Set(['hors-ligne.html', 'hors-ligne.css']);
|
|
37
|
+
|
|
38
|
+
const MARQUE_DE_VERSION = "'__VERSION__'";
|
|
39
|
+
|
|
40
|
+
/** La version d'une construction : le condense de sa page, qui nomme chacun de ses morceaux haches. */
|
|
41
|
+
export function versionDeLaConstruction(sortie) {
|
|
42
|
+
const page = join(sortie, 'index.html');
|
|
43
|
+
if (!existsSync(page)) {
|
|
44
|
+
throw new Error(`service worker : ${page} absent, construire d'abord.`);
|
|
45
|
+
}
|
|
46
|
+
return createHash('sha256').update(readFileSync(page)).digest('hex').slice(0, 16);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Pose les fichiers du service worker dans `sortie` ; rend la version posee et les fichiers que l'application fournit
|
|
51
|
+
* elle-meme (gardes). Idempotent : une seconde pose sur la meme sortie ecrit les memes octets.
|
|
52
|
+
*/
|
|
53
|
+
export function poserLeServiceWorker(sortie) {
|
|
54
|
+
const version = versionDeLaConstruction(sortie);
|
|
55
|
+
const gardes = [];
|
|
56
|
+
for (const nom of FICHIERS_DU_SERVICE_WORKER) {
|
|
57
|
+
const cible = join(sortie, nom);
|
|
58
|
+
const modele = readFileSync(join(MODELES, nom), 'utf8');
|
|
59
|
+
if (
|
|
60
|
+
FOURNIS_PAR_L_APPLICATION.has(nom) &&
|
|
61
|
+
existsSync(cible) &&
|
|
62
|
+
readFileSync(cible, 'utf8') !== modele
|
|
63
|
+
) {
|
|
64
|
+
gardes.push(nom);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (nom === 'sw.js' && !modele.includes(MARQUE_DE_VERSION)) {
|
|
68
|
+
throw new Error('service worker : le modele sw.js ne porte plus sa marque de version.');
|
|
69
|
+
}
|
|
70
|
+
writeFileSync(
|
|
71
|
+
cible,
|
|
72
|
+
nom === 'sw.js' ? modele.replace(MARQUE_DE_VERSION, `'${version}'`) : modele,
|
|
73
|
+
'utf8',
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
return { version, gardes };
|
|
77
|
+
}
|
package/src/etapes/securite.mjs
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
import { readFileSync } from 'node:fs';
|
|
30
30
|
import { dirname, join } from 'node:path';
|
|
31
31
|
import { fichiers, lireJson, relatif } from '../commun.mjs';
|
|
32
|
+
import { POLITIQUE_DU_SERVICE_WORKER } from '../construction/service-worker.mjs';
|
|
32
33
|
import { natureDesFichiers } from '../livraison.mjs';
|
|
33
34
|
|
|
34
35
|
/** Les politiques que la CSP du BFF laisse creer par defaut (application.yml du BFF). */
|
|
@@ -360,6 +361,19 @@ export function jugerUnFichierLivre(
|
|
|
360
361
|
return defauts;
|
|
361
362
|
}
|
|
362
363
|
|
|
364
|
+
/**
|
|
365
|
+
* Les politiques Trusted Types que l'application declare : un remote (lot 270), que le BFF retire s'il en exige une
|
|
366
|
+
* que sa CSP n'admet pas ; une application autonome (0.11.2), dont la page doit les porter nommement (la page d'ui-auth
|
|
367
|
+
* d'Aplomb et le widget de verification humaine) ; l'hote qui enregistre le service worker du socle (0.15.0, lot
|
|
368
|
+
* P09-49 d'Aplomb), celle de son enregistrement, que la politique de sa page doit porter avec `worker-src 'self'`.
|
|
369
|
+
* L'etape le dit des la construction.
|
|
370
|
+
*/
|
|
371
|
+
export function politiquesDeclarees(projet) {
|
|
372
|
+
if (projet.role === 'remote') return projet.source?.trustedTypes ?? [];
|
|
373
|
+
if (projet.role === 'autonome') return projet.paquet.starterWeb?.trustedTypes ?? [];
|
|
374
|
+
return projet.serviceWorker === true ? [POLITIQUE_DU_SERVICE_WORKER] : [];
|
|
375
|
+
}
|
|
376
|
+
|
|
363
377
|
export default {
|
|
364
378
|
nom: 'securite',
|
|
365
379
|
roles: ['remote', 'hote', 'autonome'],
|
|
@@ -374,23 +388,15 @@ export default {
|
|
|
374
388
|
};
|
|
375
389
|
}
|
|
376
390
|
const { partages } = natureDesFichiers(lireJson(join(projet.sortie, 'remoteEntry.json')));
|
|
377
|
-
|
|
378
|
-
// que sa CSP n'admet pas ; une application autonome (0.11.2), dont la page doit les porter nommement
|
|
379
|
-
// (la page d'ui-auth d'Aplomb et le widget de verification humaine). L'etape le dit des la construction.
|
|
380
|
-
const declarees =
|
|
381
|
-
projet.role === 'remote'
|
|
382
|
-
? (projet.source?.trustedTypes ?? [])
|
|
383
|
-
: projet.role === 'autonome'
|
|
384
|
-
? (projet.paquet.starterWeb?.trustedTypes ?? [])
|
|
385
|
-
: [];
|
|
391
|
+
const declarees = politiquesDeclarees(projet);
|
|
386
392
|
const avertissements = declarees
|
|
387
393
|
.filter((politique) => !POLITIQUES_ADMISES.includes(politique))
|
|
388
394
|
.map((politique) =>
|
|
389
|
-
projet.role === '
|
|
395
|
+
projet.role === 'remote'
|
|
390
396
|
? `trustedTypes : "${politique}" absente de la liste par defaut du BFF ` +
|
|
391
|
-
'(PLATFORM_WEB_CSP_TRUSTED_TYPES) :
|
|
397
|
+
'(PLATFORM_WEB_CSP_TRUSTED_TYPES) : le BFF retire le remote tant qu elle n y est pas.'
|
|
392
398
|
: `trustedTypes : "${politique}" absente de la liste par defaut du BFF ` +
|
|
393
|
-
'(PLATFORM_WEB_CSP_TRUSTED_TYPES) :
|
|
399
|
+
'(PLATFORM_WEB_CSP_TRUSTED_TYPES) : la page de l application doit la porter nommement.',
|
|
394
400
|
);
|
|
395
401
|
const defauts = [];
|
|
396
402
|
// 0.11.7 : les admissions nommees, et la carte de la construction qui dit les sources de chaque morceau.
|
package/src/projet.mjs
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* - le nom et `pleinePage` : `manifest.source.json` (un remote), `socle` pour l'hote ;
|
|
12
12
|
* - le prefixe : `prefix` du projet d'`angular.json`, ou `starterWeb.prefixe` ;
|
|
13
13
|
* - le prerendu : `starterWeb.prerendu` (une application autonome servie en pages statiques, 0.11.4) ;
|
|
14
|
+
* - le service worker minimal : `starterWeb.serviceWorker` (l'hote seul, lot P09-49 d'Aplomb, 0.15.0) ;
|
|
14
15
|
* - le dossier livre : `outputPath` de la cible `@angular/build:application`, plus `browser`.
|
|
15
16
|
*
|
|
16
17
|
* Les options de la ligne de commande (`--nom`, `--prefixe`, `--pleine-page`) les remplacent : ce
|
|
@@ -76,6 +77,14 @@ export function lireLeProjet(racine, options = {}) {
|
|
|
76
77
|
`starterWeb.prerendu : reserve a une application autonome, pas a un role "${role}".`,
|
|
77
78
|
);
|
|
78
79
|
}
|
|
80
|
+
// Le service worker minimal (lot P09-49 d'Aplomb) : celui d'un hote, qui sert ses navigations ; jamais celui d'un
|
|
81
|
+
// remote (il vit sous le perimetre de l'hote) ni d'une application autonome (l'ecran anonyme, l'urgence).
|
|
82
|
+
const serviceWorker = reglages.serviceWorker === true;
|
|
83
|
+
if (serviceWorker && role !== 'hote') {
|
|
84
|
+
throw new ProjetIllisible(
|
|
85
|
+
`starterWeb.serviceWorker : reserve a l'hote, pas a un role "${role}".`,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
79
88
|
const source = role === 'remote' ? lireJson(cheminSource) : null;
|
|
80
89
|
if (role === 'remote' && source === null) {
|
|
81
90
|
throw new ProjetIllisible('manifest.source.json absent ou illisible : un remote en a un.');
|
|
@@ -100,6 +109,7 @@ export function lireLeProjet(racine, options = {}) {
|
|
|
100
109
|
prefixe: options.prefixe ?? reglages.prefixe ?? projet.prefix ?? null,
|
|
101
110
|
pleinePage: options.pleinePage ?? source?.pleinePage === true,
|
|
102
111
|
prerendu,
|
|
112
|
+
serviceWorker,
|
|
103
113
|
source,
|
|
104
114
|
nomDuProjetAngular: nomDuProjet,
|
|
105
115
|
sortieRelative: sortie.split('\\').join('/'),
|