@mostajs/mjs-unit 0.11.2 → 0.13.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
@@ -164,6 +164,91 @@ La clé de CI (opération « pousser ») : `QATRAX_CLE_CI`, sinon `~/.config/qat
164
164
  qatrax prévient de son côté (webhook signé, courriel) quand un rapport de recette arrive. En code :
165
165
  `import { configQatrax, creerClientQatrax } from '@mostajs/mjs-unit/qatrax'`.
166
166
 
167
+ ## La suite une fois, en parallèle — S1P (0.12.0)
168
+
169
+ S1P — « suite une fois, en parallèle » (règle DEVRULES-S1P du 04/11/2026, premier usage : Guerway, 371 essais).
170
+
171
+ - **`--jobs=N`** (ou `--jobs` / `--jobs=auto` : nombre de processeurs, 4 au plus) : les fichiers sont répartis en N lots de
172
+ durée voisine (durées du rapport `--json` précédent), un processus par lot, puis réunis en UN rapport ; le total
173
+ exécuté reste vérifié contre le total déclaré. Une chaîne de fichiers marquée `// mjs-unit:lot <nom>` reste dans un même lot.
174
+ - **Le bloc `execution` du rapport JSON** (et une ligne ⏱ en sortie et dans le HTML) : mode, lots, durée réelle,
175
+ somme des durées des essais, gain, détail de chaque lot, espace, jeux de données, empreinte.
176
+ - **L'espace propre** : chaque suite a son `TMPDIR` dédié (un sous-espace par lot) ; ce que chaque fichier d'essai y laisse
177
+ est relevé (bases SQLite reconnues à leur en-tête, fichiers, octets), puis l'espace est supprimé, réussite ou échec ;
178
+ `--garder` le conserve pour examen. Fini les bases d'essai laissées dans `/tmp` (constaté : 16 036 dossiers, 26 Go).
179
+ - **`jeu(nom, { pour, construire, detruire })`** : un jeu de données partagé (un compte, puis une autorisation sur ce compte)
180
+ construit au premier `obtenir()`, gardé tant qu'un essai de `pour` n'a pas fini, détruit après le DERNIER ; un essai
181
+ déclaré jamais exécuté est une anomalie relevée.
182
+ - **`mjs-unit rejouer <essai> <fichier...>`** : cet essai seul, dans un espace neuf ; ses jeux de données sont reconstruits.
183
+ - **L'empreinte** de ce qui a été éprouvé (commit, arbre propre, empreinte du `package-lock.json`, Node) au bloc `execution`,
184
+ et **`mjs-unit empreinte --verifier=<rapport.json>`** : code 0 si le rapport vaut encore pour l'arbre courant, sinon les motifs
185
+ (c'est ce qui permet de ne pas rejouer une suite après une fusion `--ff-only`).
186
+
187
+ ```bash
188
+ npx mjs-unit test-scripts/*.test.mjs --jobs --json=test-scripts/.out/report.json --report=test-scripts/.out/report.html
189
+ npx mjs-unit rejouer T-CMP-4 test-scripts/comptes.test.mjs --garder
190
+ npx mjs-unit empreinte --verifier=test-scripts/.out/report.json
191
+ ```
192
+
193
+ ```js
194
+ import { test, jeu } from "@mostajs/mjs-unit";
195
+ const compte = jeu("compte", { pour: ["T-CMP-1", "T-CMP-2"], construire: () => creerCompte(), detruire: (c) => supprimer(c) });
196
+ test("T-CMP-1 — crée le compte", async () => { const c = await compte.obtenir(); /* … */ });
197
+ test("T-CMP-2 — une autorisation sur le compte existant", async () => { const c = await compte.obtenir(); /* … */ });
198
+ ```
199
+
200
+ ## Après la suite — D4Q et D4PF (0.13.0)
201
+
202
+ Deux commandes pour ce qui suit une version **intégrée** (suite S1P verte, `main` avancé) ; premier usage : Guerway
203
+ (04/11/2026). L'application décrit ses étapes dans **`d4.config.json`** ; mjs-unit les enchaîne avec les mêmes règles partout.
204
+
205
+ **L'ordre d'une version** : essais rouges → code → suite (`--jobs`, rapport JSON) → intégration S1P
206
+ (`mjs-unit empreinte --verifier`, fusion `--ff-only`) → **`mjs-unit d4q`** → **`mjs-unit d4pf` sur feu vert**.
207
+
208
+ ```bash
209
+ npx mjs-unit d4q # la qualité : ne déploie RIEN (CAPTURES=0 saute une étape marquée « sauterSi »)
210
+ npx mjs-unit d4q ../worktrees/L2-1.4.0 # sur un autre dossier de l'application (un worktree)
211
+ npx mjs-unit d4pf --a-blanc # contrôles, puis les commandes qui seraient lancées ; rien n'est exécuté
212
+ npx mjs-unit d4pf # SEULEMENT sur feu vert explicite pour CETTE version
213
+ npx mjs-unit d4pfq # D4PF puis D4Q (D4Q seulement si D4PF réussit) — sur feu vert ; --a-blanc aussi
214
+ ```
215
+
216
+ ### D4Q — « déploie pour la qualité »
217
+
218
+ Régénère et publie tout ce qui sert à juger la version, dans l'ordre déclaré (chez Guerway : cahier des écrans, feuilles
219
+ de recette par rôle, feuilles de formation, plan Dev+Test, avancement, chiffrage, `mjs-unit qatrax pousser plan,run`).
220
+
221
+ - `exige` : les fichiers sans lesquels D4Q refuse (le rapport de la DERNIÈRE suite : `test-scripts/.out/report.json`) ;
222
+ - chaque étape s'arrête au premier échec, sauf si sa sortie contient son motif `reporterSi` (un quota de service de PDF) :
223
+ elle est alors « reportée » et la suite continue ; `sauterSi: "VAR=valeur"` la saute ;
224
+ - `dossier` : `app` (défaut) ou `racine` (le dossier de `d4.config.json`) ; `lignes` : les dernières lignes montrées.
225
+
226
+ ### D4PF — « déploie pour prod et formation »
227
+
228
+ 1. contrôles : la branche (`main`), aucun fichier suivi modifié hors `ignorer` (expressions sur `git status --porcelain`) ;
229
+ 2. `sauvegardes` : chaque commande écrit sa copie dans `fichier` ; vide ou sans `entete` (ex. `PGDMP`) → arrêt AVANT
230
+ tout déploiement ;
231
+ 3. et 4. `deploiements`, dans l'ordre (production, puis formation) ;
232
+ 5. `sante` : chaque commande rend le JSON de `/health` ; `ok`, `version` du package.json ET `commit` de `main` exigés ;
233
+ 6. `journaux` : les dernières erreurs, pour lecture (des lignes anciennes ne sont pas une erreur de la version).
234
+
235
+ Règles : aucune valeur du `.env` affichée ; ne pas figer la liste des processus du serveur (pas de `pm2 save`) ; le
236
+ `push` et la publication npm restent hors de D4PF. Jetons des commandes : `{racine}`, `{app}`, `{version}`, `{commit}`, `{date}`.
237
+
238
+ ```json
239
+ {
240
+ "app": "mon-api",
241
+ "d4q": { "exige": ["test-scripts/.out/report.json"], "etapes": [
242
+ { "titre": "feuilles de recette", "commande": "node outils/feuillets.mjs", "reporterSi": "QUOTA_EXCEEDED" },
243
+ { "titre": "qatrax", "commande": "npx mjs-unit qatrax pousser plan,run" } ] },
244
+ "d4pf": { "branche": "main", "ignorer": [" \\.env\\.example$"],
245
+ "sauvegardes": [{ "nom": "production", "commande": "ssh serveur 'pg_dump -Fc \"$BASE\"'", "fichier": "sauvegardes/avant-{version}-{date}.dump", "entete": "PGDMP" }],
246
+ "deploiements": [{ "nom": "production", "commande": "bash deploy.sh ./prod.conf" }, { "nom": "formation", "commande": "bash deploy.sh ./formation.conf" }],
247
+ "sante": [{ "nom": "production", "commande": "ssh serveur 'curl -s http://127.0.0.1:5400/health'" }],
248
+ "journaux": "ssh serveur 'tail -n 5 logs/err.log'" }
249
+ }
250
+ ```
251
+
167
252
  ## API
168
253
 
169
254
  | Fonction | Rôle |
package/bin/cli.mjs CHANGED
@@ -5,6 +5,8 @@
5
5
  *
6
6
  * Usage : mjs-unit <fichier-de-test...> [options]
7
7
  * --report[=fichier] écrit une preuve HTML (défaut : test-report.html)
8
+ * --jobs[=N|auto] 0.12.0 (S1P) : N lots parallèles, un seul rapport ; --garder : garde l'espace des essais
9
+ * rejouer <essai> <f…> 0.12.0 : cet essai seul, dans un espace neuf · empreinte --verifier=<rapport.json>
8
10
  * --json[=fichier] écrit un rapport JSON (défaut : test-report.json)
9
11
  * --junit[=fichier] écrit un rapport JUnit XML (défaut : test-report.xml) — Jenkins, GitLab, GitHub, QATrax
10
12
  * --timeout=ms délai par défaut de chaque cas (un cas le surcharge par { timeout })
@@ -22,6 +24,7 @@
22
24
  * JUnit XML, NUnit 2/3, TRX, TestNG, Robot Framework, CTest, Cucumber JSON, Behave JSON,
23
25
  * Allure 2, CTRF, TAP, JSON mjs-unit — reconnus à leur contenu
24
26
  * 0.11.0 — LE CLIENT QATRAX : mjs-unit qatrax <etat|rapatrier|pris|corrige|pousser> (voir : mjs-unit qatrax aide)
27
+ * 0.13.0 — mjs-unit d4q [dossier] | d4pf | d4pfq (D4PF puis D4Q) [--config=d4.config.json] [--a-blanc] : feu vert pour d4pf*
25
28
  * --depuis=chemin un dossier (tous ses .xml, .json, .tap, .trx ; dans allure-results, les *-container et
26
29
  * *-attachment sont écartés) ou un fichier
27
30
  * → les mêmes sorties : --compte-rendu, --ctrf, --intoto, --json, --junit, --report
@@ -29,22 +32,42 @@
29
32
  * @author Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
30
33
  */
31
34
  // 0.11.0 — `mjs-unit qatrax …` : le client qatrax, chargé SEULEMENT pour cette sous-commande (le runner reste sans réseau).
35
+ // 0.13.0 — `mjs-unit d4q` / `mjs-unit d4pf` : ce qui suit une version intégrée, décrit par l'app dans d4.config.json.
36
+ if (process.argv[2] === "d4q" || process.argv[2] === "d4pf" || process.argv[2] === "d4pfq") {
37
+ const d4 = await import("../dist/d4.js");
38
+ process.exit(d4[process.argv[2]](process.argv.slice(3)));
39
+ }
32
40
  if (process.argv[2] === "qatrax") {
33
41
  const { principal } = await import("../dist/qatrax.js");
34
42
  process.exit(await principal(process.argv.slice(3)));
35
43
  }
36
44
  import { register } from "node:module";
37
45
  import { pathToFileURL } from "node:url";
38
- import { writeFileSync, readFileSync, mkdirSync, statSync, readdirSync } from "node:fs";
39
- import { hostname } from "node:os";
46
+ import { writeFileSync, readFileSync, mkdirSync, statSync, readdirSync, mkdtempSync, rmSync } from "node:fs";
47
+ import { hostname, tmpdir, availableParallelism } from "node:os";
48
+ import { spawn } from "node:child_process";
49
+ import { fileURLToPath } from "node:url";
40
50
  import { createHash } from "node:crypto";
41
51
  import { dirname, join } from "node:path";
42
52
 
43
53
  register(new URL("../loader.mjs", import.meta.url));
44
- const { run, pending, registered, takeRuns, setDefaultTimeout, setTagFilter } = await import("../dist/index.js");
54
+ const { run, pending, registered, takeRuns, setDefaultTimeout, setTagFilter, setSeul, takeJeux } = await import("../dist/index.js");
55
+ const { photographier, releverEntre, empreinteDe, verifierEmpreinte, repartir, dureesDe } = await import("../dist/s1p.js");
45
56
 
46
57
  // ── Découpe arguments / options ──────────────────────────────────────────────
47
58
  const argv = process.argv.slice(2);
59
+ // 0.12.0 (S1P) — `mjs-unit empreinte --verifier=<rapport.json>` : le rapport vaut-il encore pour l'arbre courant ?
60
+ if (argv[0] === "empreinte") {
61
+ const f = (argv.find((a) => a.startsWith("--verifier=")) || "").slice(11);
62
+ if (!f) { console.error("usage : mjs-unit empreinte --verifier=<rapport.json>"); process.exit(2); }
63
+ let r; try { r = JSON.parse(readFileSync(f, "utf8")); } catch (e) { console.error(`✗ ${f} : ${e?.message ?? e}`); process.exit(2); }
64
+ const v = verifierEmpreinte(r.execution?.empreinte, process.cwd());
65
+ if (v.ok) { console.log(`✓ le rapport vaut pour l'arbre courant : commit ${String(v.actuelle.commit).slice(0, 7)}, arbre propre, même verrou, Node ${v.actuelle.node}`); process.exit(0); }
66
+ console.log(`✗ le rapport ne vaut plus pour l'arbre courant :\n${v.motifs.map((m) => ` - ${m}`).join("\n")}`); process.exit(1);
67
+ }
68
+ // 0.12.0 (S1P) — `mjs-unit rejouer <essai> <fichier...>` : cet essai seul, dans un espace neuf (ses jeux reconstruits).
69
+ let rejouer = null;
70
+ if (argv[0] === "rejouer") { rejouer = argv[1]; argv.splice(0, 2); if (!rejouer || rejouer.startsWith("--")) { console.error("usage : mjs-unit rejouer <essai> <fichier...>"); process.exit(2); } }
48
71
  const opt = (name) => {
49
72
  const hit = argv.find((a) => a === `--${name}` || a.startsWith(`--${name}=`));
50
73
  if (!hit) return undefined;
@@ -62,6 +85,24 @@ const depuis = opt("depuis"); // 0.10.0 — mode lecteur : "" (les arguments
62
85
  const lecteur = depuis !== undefined;
63
86
  const files = argv.filter((a) => !a.startsWith("--"));
64
87
  const debut = new Date().toISOString();
88
+ // ── 0.12.0 (S1P) — l'espace des essais, le parallèle, l'empreinte ─────────────────────────────────────────────
89
+ // Chaque suite a son ESPACE (TMPDIR dédié) : bases et fichiers des essais y naissent, sont relevés par fichier, puis
90
+ // supprimés (réussite ou échec) — sauf --garder. --jobs=N répartit les fichiers en N lots parallèles (un processus par
91
+ // lot, son sous-espace), puis réunit leurs rapports en un seul. Le bloc `execution` du rapport dit tout (chrono, gain,
92
+ // lots, espace, jeux de données, empreinte). --lot et --espace sont internes (un lot lancé par le CLI parent).
93
+ const t0 = Date.now();
94
+ const garder = opt("garder") !== undefined;
95
+ const enfant = opt("lot") !== undefined;
96
+ const jobsOpt = opt("jobs");
97
+ const jobs = jobsOpt === undefined ? 1 : (jobsOpt === "" || jobsOpt === "auto") ? Math.min(4, availableParallelism()) : Math.max(1, Number.parseInt(jobsOpt, 10) || 1);
98
+ const empreinte = lecteur ? null : empreinteDe(process.cwd());
99
+ let espace = null;
100
+ if (!lecteur) { espace = opt("espace") || mkdtempSync(join(tmpdir(), "mjs-unit-")); mkdirSync(espace, { recursive: true }); process.env.TMPDIR = espace; }
101
+ if (rejouer) setSeul([rejouer]);
102
+ const parallele = !lecteur && !enfant && jobs > 1 && files.length > 1;
103
+ const parFichier = [], lotsExec = [];
104
+ const jeux = { construits: 0, detruits: 0, anomalies: [] };
105
+ const ajouterJeux = (j) => { jeux.construits += j.construits || 0; jeux.detruits += j.detruits || 0; jeux.anomalies.push(...(j.anomalies || [])); };
65
106
  if (!files.length && !depuis) { console.error("usage: mjs-unit <fichier-de-test...> [--report[=f]] [--json[=f]] — ou : mjs-unit --depuis <rapport...> (JUnit, NUnit, TRX, TestNG, Robot, CTest, Cucumber, Behave, Allure, CTRF, TAP)"); process.exit(2); }
66
107
 
67
108
  // ── Exécution, une suite par fichier ─────────────────────────────────────────
@@ -108,7 +149,35 @@ if (lecteur) {
108
149
  if (allure.length) ajouter(lireRapportEssais(allure).rapport, allureSource);
109
150
  console.log(`\n${totalFail ? "✗" : "✓"} ${totalExecutes} cas lu(s) dans ${lecture.rapports.length} rapport(s) — mode lecteur : aucun essai exécuté par mjs-unit`);
110
151
  }
111
- for (const f of lecteur ? [] : files) {
152
+ if (parallele) {
153
+ const groupes = repartir(files, jobs, dureesDe(jsonOut || undefined));
154
+ console.log(`S1P : ${files.length} fichiers en ${groupes.length} lots parallèles (--jobs=${jobs})`);
155
+ const transmis = argv.filter((a) => /^--(timeout|tag)=/.test(a));
156
+ const lots = await Promise.all(groupes.map((g, i) => new Promise((ok) => {
157
+ const dir = join(espace, `lot-${i}`); mkdirSync(dir, { recursive: true });
158
+ const json = join(espace, `lot-${i}.json`);
159
+ const debutLot = Date.now();
160
+ const p = spawn(process.execPath, [fileURLToPath(import.meta.url), ...(rejouer ? ["rejouer", rejouer] : []), ...g, `--json=${json}`, `--lot=${i}`, `--espace=${dir}`, ...transmis],
161
+ { env: { ...process.env, TMPDIR: dir }, stdio: ["ignore", "pipe", "pipe"] });
162
+ let sortie = ""; p.stdout.on("data", (d) => { sortie += d; }); p.stderr.on("data", (d) => { sortie += d; });
163
+ p.on("close", (code) => ok({ i, g, code, sortie, json, dureeMs: Date.now() - debutLot }));
164
+ })));
165
+ for (const l of lots) {
166
+ process.stdout.write(`\n── lot ${l.i} (${l.g.length} fichier(s), ${Math.round(l.dureeMs / 1000)} s) ──${l.sortie.startsWith("\n") ? "" : "\n"}${l.sortie}`);
167
+ let rap = null; try { rap = JSON.parse(readFileSync(l.json, "utf8")); } catch {}
168
+ if (!rap) { console.error(`\n✗ lot ${l.i} : aucun rapport (code ${l.code}) — ${l.g.join(", ")}`); totalFail++; continue; }
169
+ const res = rap.suites.flatMap((s) => s.results);
170
+ suites.push(...rap.suites);
171
+ const x = rap.execution || {};
172
+ totalDeclares += x.declares || 0; totalExecutes += x.executes || 0;
173
+ const echecs = res.filter((r) => r.status === "fail").length;
174
+ totalFail += echecs; if (l.code !== 0 && !echecs) totalFail++;
175
+ lotsExec.push({ n: l.i, fichiers: l.g, essais: res.filter((r) => !r.hook).length, dureeMs: l.dureeMs });
176
+ parFichier.push(...(x.espace?.parFichier || [])); ajouterJeux(x.espace?.jeux || {});
177
+ }
178
+ }
179
+ for (const f of lecteur || parallele ? [] : files) {
180
+ const photoAvant = photographier(espace);
112
181
  const avant = registered();
113
182
  takeRuns(); // rien d'un fichier précédent ne doit être attribué à celui-ci
114
183
  await import(pathToFileURL(f).href); // le fichier enregistre ses cas (et peut appeler run() lui-même)
@@ -130,13 +199,34 @@ for (const f of lecteur ? [] : files) {
130
199
  }
131
200
  totalDeclares += declares; totalExecutes += cas.length;
132
201
  suites.push({ file: f, results });
202
+ parFichier.push({ fichier: f, ...releverEntre(photoAvant, photographier(espace)) });
203
+ ajouterJeux(takeJeux());
204
+ }
205
+ // Le bloc `execution` : chrono, gain, lots, espace, jeux de données, empreinte (0.12.0, S1P).
206
+ let execution = null;
207
+ if (!lecteur) {
208
+ if (rejouer && !enfant && !suites.flatMap((s) => s.results).some((r) => r.status !== "skip" && String(r.name).trim().split(/\s+/)[0] === rejouer)) {
209
+ console.error(`\n✗ rejouer : aucun essai « ${rejouer} » dans ces fichiers.`); totalFail++;
210
+ }
211
+ const cas = suites.flatMap((s) => s.results).filter((r) => !r.hook);
212
+ const somme = Math.round(cas.reduce((a, r) => a + (r.durationMs || 0), 0));
213
+ const dureeMs = Date.now() - t0;
214
+ const total = (k) => parFichier.reduce((a, p) => a + (p[k] || 0), 0);
215
+ execution = {
216
+ mode: parallele ? "parallele" : "file", jobs: parallele ? jobs : 1, debut, fin: new Date().toISOString(), dureeMs, sommeEssaisMs: somme,
217
+ gainPourcent: somme ? Math.round((100 * (somme - dureeMs)) / somme) : 0, executes: totalExecutes, declares: totalDeclares,
218
+ lots: parallele ? lotsExec : [{ n: 0, fichiers: files, essais: cas.length, dureeMs }],
219
+ espace: { dossier: espace, garde: garder, bases: total("bases"), fichiers: total("fichiers"), octets: total("octets"), parFichier, jeux },
220
+ empreinte, ...(rejouer ? { rejouer } : {}),
221
+ };
222
+ if (!enfant) console.log(`\n⏱ ${execution.mode === "parallele" ? `S1P — ${lotsExec.length} lots parallèles` : "à la file"} : ${(dureeMs / 1000).toFixed(1)} s (somme des essais ${(somme / 1000).toFixed(1)} s, gain ${execution.gainPourcent} %) — espace : ${execution.espace.bases} base(s), ${execution.espace.fichiers} fichier(s), ${Math.round(execution.espace.octets / 1024)} Ko${garder ? ` gardés dans ${espace}` : ", supprimés"}${jeux.anomalies.length ? ` — ${jeux.anomalies.length} anomalie(s) de jeux de données` : ""}`);
133
223
  }
134
224
  if (!lecteur) console.log(`\n${totalExecutes === totalDeclares ? "✓" : "✗"} ${totalExecutes}/${totalDeclares} test(s) exécutés sur ${suites.length} fichier(s) — compte relevé auprès du module, pas supposé`);
135
225
 
136
226
  // ── Reporters optionnels ─────────────────────────────────────────────────────
137
227
  if (htmlOut !== undefined || jsonOut !== undefined || junitOut !== undefined) {
138
228
  const { renderHtmlReport, renderJsonReport, renderJunitReport } = await import("../dist/report.js");
139
- const report = { suites, generatedAt: genereLe ?? new Date().toISOString(), title: title || undefined, hostname: hostname() };
229
+ const report = { suites, generatedAt: genereLe ?? new Date().toISOString(), title: title || undefined, hostname: hostname(), ...(execution ? { execution } : {}) };
140
230
  if (htmlOut !== undefined) {
141
231
  const out = htmlOut || "test-report.html";
142
232
  writeFileSync(out, renderHtmlReport(report));
@@ -181,4 +271,6 @@ if (crOut !== undefined || ctrfOut !== undefined || intotoOut !== undefined) {
181
271
  }
182
272
  }
183
273
 
274
+ // L'espace est supprimé — réussite ou échec — sauf --garder ; l'espace d'un lot, par le parent.
275
+ if (espace && !garder && !enfant) { try { rmSync(espace, { recursive: true, force: true }); } catch {} }
184
276
  if (totalFail > 0) process.exitCode = 1;
package/dist/d4.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ export interface Etape {
2
+ titre?: string;
3
+ nom?: string;
4
+ commande: string;
5
+ dossier?: "app" | "racine";
6
+ lignes?: number;
7
+ reporterSi?: string;
8
+ sauterSi?: string;
9
+ }
10
+ export interface Sauvegarde {
11
+ nom: string;
12
+ commande: string;
13
+ fichier: string;
14
+ entete?: string;
15
+ }
16
+ export interface Sante {
17
+ nom: string;
18
+ commande: string;
19
+ champs?: string[];
20
+ }
21
+ export interface ConfigD4 {
22
+ app?: string;
23
+ d4q?: {
24
+ exige?: string[];
25
+ etapes: Etape[];
26
+ };
27
+ d4pf?: {
28
+ branche?: string;
29
+ ignorer?: string[];
30
+ sauvegardes?: Sauvegarde[];
31
+ deploiements?: Etape[];
32
+ sante?: Sante[];
33
+ journaux?: string;
34
+ };
35
+ }
36
+ /** Remplace les jetons {x} d'une commande. */
37
+ export declare function jetons(texte: string, valeurs: Record<string, string>): string;
38
+ /** D4Q : régénère et publie ce qui sert à juger la version ; ne déploie rien. → code de sortie. */
39
+ export declare function d4q(argv: string[]): number;
40
+ /** D4PF : déploie main sur la production et la formation — SEULEMENT sur feu vert pour CETTE version. → code de sortie. */
41
+ export declare function d4pf(argv: string[]): number;
42
+ /** D4PFQ : D4PF puis D4Q — D4Q seulement si D4PF a réussi. SEULEMENT sur feu vert pour CETTE version. → code de sortie. */
43
+ export declare function d4pfq(argv: string[]): number;
44
+ //# sourceMappingURL=d4.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"d4.d.ts","sourceRoot":"","sources":["../src/d4.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,KAAK;IAAG,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;AAC9J,MAAM,WAAW,UAAU;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE;AAC/F,MAAM,WAAW,KAAK;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE;AAC3E,MAAM,WAAW,QAAQ;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,KAAK,EAAE,CAAA;KAAE,CAAC;IAC5C,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;QAAC,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACzI;AAOD,8CAA8C;AAC9C,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAE7E;AAqBD,mGAAmG;AACnG,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CA4B1C;AAQD,2HAA2H;AAC3H,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CA+D3C;AAED,2HAA2H;AAC3H,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ5C"}
package/dist/d4.js ADDED
@@ -0,0 +1,225 @@
1
+ /**
2
+ * @mostajs/mjs-unit — D4Q et D4PF (0.13.0) : ce qui suit une version INTÉGRÉE (suite S1P verte, main avancé).
3
+ *
4
+ * mjs-unit d4q [dossier-de-l-app] [--config=d4.config.json] « déploie pour la qualité » : ne déploie RIEN ;
5
+ * mjs-unit d4pfq [--config=…] [--a-blanc] D4PF puis D4Q (D4Q seulement si D4PF réussit) : sur FEU VERT ;
6
+ * mjs-unit d4pf [--config=d4.config.json] [--a-blanc] « déploie pour prod et formation » : sur FEU VERT
7
+ * (--a-blanc : contrôles, puis les commandes, sans rien lancer).
8
+ *
9
+ * L'application décrit ses étapes dans `d4.config.json` (cherché dans le dossier courant) ; mjs-unit les enchaîne avec
10
+ * les mêmes règles partout : arrêt au premier échec, une étape « reportée » sur un motif déclaré (quota d'un service
11
+ * de PDF), une étape sautée par variable d'environnement ; pour D4PF : branche et arbre propre exigés, chaque
12
+ * sauvegarde vérifiée (non vide, en-tête attendu) AVANT tout déploiement, santé = version du package.json ET commit.
13
+ * Jetons des commandes : {racine} (dossier de la config), {app}, {version}, {commit}, {date} (AAAAMMJJ-HHMM).
14
+ * Premier usage : Guerway (outils/d4q.sh, outils/d4pf.sh, 04/11/2026).
15
+ * @author Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
16
+ */
17
+ import { spawnSync } from "node:child_process";
18
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync, openSync, readSync, closeSync } from "node:fs";
19
+ import { dirname, join, resolve, basename, isAbsolute } from "node:path";
20
+ const BLEU = (s) => `\x1b[0;36m${s}\x1b[0m`;
21
+ const VERT = (s) => `\x1b[0;32m${s}\x1b[0m`;
22
+ const deuxChiffres = (n) => String(n).padStart(2, "0");
23
+ const dateCourte = (d = new Date()) => `${d.getFullYear()}${deuxChiffres(d.getMonth() + 1)}${deuxChiffres(d.getDate())}-${deuxChiffres(d.getHours())}${deuxChiffres(d.getMinutes())}`;
24
+ /** Remplace les jetons {x} d'une commande. */
25
+ export function jetons(texte, valeurs) {
26
+ return texte.replace(/\{(racine|app|version|commit|date)\}/g, (m, k) => (k in valeurs ? valeurs[k] : m));
27
+ }
28
+ function shell(commande, cwd) {
29
+ const r = spawnSync("bash", ["-c", commande], { cwd, encoding: "utf8", env: process.env, maxBuffer: 256 * 1024 * 1024 });
30
+ return { code: r.status ?? 1, sortie: `${r.stdout ?? ""}${r.stderr ?? ""}` };
31
+ }
32
+ const fin = (s, n = 3) => s.trimEnd().split("\n").slice(-n).join("\n");
33
+ function charger(argv) {
34
+ const opt = argv.find((a) => a.startsWith("--config="));
35
+ const fichier = resolve(opt ? opt.slice(9) : "d4.config.json");
36
+ if (!existsSync(fichier))
37
+ throw Object.assign(new Error(`${fichier} introuvable : décrivez les étapes de l'application dans d4.config.json`), { code: 2 });
38
+ const config = JSON.parse(readFileSync(fichier, "utf8"));
39
+ const racine = dirname(fichier);
40
+ const libres = argv.filter((a) => !a.startsWith("--"));
41
+ const app = libres[0] ? resolve(libres[0]) : resolve(racine, config.app || ".");
42
+ if (!existsSync(join(app, "package.json")))
43
+ throw Object.assign(new Error(`${app} : pas de package.json (dossier de l'application attendu)`), { code: 1 });
44
+ const pkg = JSON.parse(readFileSync(join(app, "package.json"), "utf8"));
45
+ return { config, racine, app, version: String(pkg.version), nom: String(pkg.name || basename(app)), libres };
46
+ }
47
+ /** D4Q : régénère et publie ce qui sert à juger la version ; ne déploie rien. → code de sortie. */
48
+ export function d4q(argv) {
49
+ let c;
50
+ try {
51
+ c = charger(argv);
52
+ }
53
+ catch (e) {
54
+ console.error(`✗ ${e.message}`);
55
+ return e.code ?? 1;
56
+ }
57
+ const q = c.config.d4q;
58
+ if (!q || !q.etapes?.length) {
59
+ console.error("✗ aucune section d4q (etapes) dans d4.config.json");
60
+ return 2;
61
+ }
62
+ const valeurs = { racine: c.racine, app: c.app, version: c.version, commit: "", date: dateCourte() };
63
+ console.log(`D4Q — ${c.nom} ${c.version} (${c.app})`);
64
+ for (const f of q.exige || [])
65
+ if (!existsSync(join(c.app, f))) {
66
+ console.error(`✗ aucune exécution : ${f} manque — lancer d'abord la suite dans ${c.app}`);
67
+ return 1;
68
+ }
69
+ const n = q.etapes.length;
70
+ const reportees = [];
71
+ if (argv.includes("--a-blanc")) {
72
+ for (const [i, e] of q.etapes.entries())
73
+ console.log(` [${i + 1}/${n}] ${e.titre} : ${jetons(e.commande, valeurs)}`);
74
+ console.log(`\n${VERT("✓ D4Q à blanc — rien n'a été lancé")}`);
75
+ return 0;
76
+ }
77
+ for (const [i, e] of q.etapes.entries()) {
78
+ const k = i + 1;
79
+ if (e.sauterSi) {
80
+ const [v, val] = e.sauterSi.split("=");
81
+ if (process.env[v] === val) {
82
+ console.log(`\n${BLEU(`[${k}/${n}] ${e.titre} — sautée (${e.sauterSi})`)}`);
83
+ continue;
84
+ }
85
+ }
86
+ console.log(`\n${BLEU(`[${k}/${n}] ${e.titre}`)}`);
87
+ const r = shell(jetons(e.commande, valeurs), e.dossier === "racine" ? c.racine : c.app);
88
+ if (r.code === 0) {
89
+ if (r.sortie.trim())
90
+ console.log(fin(r.sortie, e.lignes ?? 3));
91
+ continue;
92
+ }
93
+ if (e.reporterSi && r.sortie.includes(e.reporterSi)) {
94
+ console.log(` ⚠ reportée : ${e.reporterSi} (les sources sont à jour ; relancer D4Q plus tard)`);
95
+ reportees.push(k);
96
+ continue;
97
+ }
98
+ console.log(fin(r.sortie, 15));
99
+ console.error(`✗ étape ${k} en échec`);
100
+ return 1;
101
+ }
102
+ if (reportees.length)
103
+ console.log(`⚠ étapes reportées : ${reportees.join(", ")} ; relancer D4Q pour les produire.`);
104
+ console.log(`\n${VERT(`✓ D4Q terminé — ${c.nom} ${c.version}`)}`);
105
+ return 0;
106
+ }
107
+ /** Les premiers octets d'un fichier. */
108
+ function debut(fichier, n) {
109
+ const fd = openSync(fichier, "r");
110
+ const b = Buffer.alloc(n);
111
+ const lus = readSync(fd, b, 0, n, 0);
112
+ closeSync(fd);
113
+ return b.subarray(0, lus).toString("latin1");
114
+ }
115
+ /** D4PF : déploie main sur la production et la formation — SEULEMENT sur feu vert pour CETTE version. → code de sortie. */
116
+ export function d4pf(argv) {
117
+ let c;
118
+ try {
119
+ c = charger(argv);
120
+ }
121
+ catch (e) {
122
+ console.error(`✗ ${e.message}`);
123
+ return e.code ?? 1;
124
+ }
125
+ const d = c.config.d4pf;
126
+ if (!d) {
127
+ console.error("✗ aucune section d4pf dans d4.config.json");
128
+ return 2;
129
+ }
130
+ const git = (a) => shell(`git ${a}`, c.app).sortie.trim();
131
+ const commit = git("rev-parse --short HEAD");
132
+ const valeurs = { racine: c.racine, app: c.app, version: c.version, commit, date: dateCourte() };
133
+ const pas = (k, t) => console.log(`\n${BLEU(`[${k}/6] ${t}`)}`);
134
+ console.log(`D4PF — ${c.nom} ${c.version} (${commit})`);
135
+ pas(1, "contrôles");
136
+ const branche = d.branche || "main";
137
+ const courante = git("branch --show-current");
138
+ if (courante !== branche) {
139
+ console.error(`✗ branche courante : ${courante} (${branche} attendu)`);
140
+ return 1;
141
+ }
142
+ const ignorer = (d.ignorer || []).map((x) => new RegExp(x));
143
+ const sale = git("status --porcelain --untracked-files=no").split("\n").filter((l) => l.trim() && !ignorer.some((re) => re.test(l)));
144
+ if (sale.length) {
145
+ console.error(`✗ fichiers suivis modifiés :\n${sale.join("\n")}`);
146
+ return 1;
147
+ }
148
+ console.log(` ✓ ${branche}, arbre propre${ignorer.length ? " (hors fichiers ignorés)" : ""}`);
149
+ // --a-blanc : les contrôles seuls, puis les commandes qui seraient lancées (jetons remplacés) ; rien n'est exécuté.
150
+ if (argv.includes("--a-blanc")) {
151
+ const l = (t, x) => console.log(` ${t} : ${jetons(x, valeurs)}`);
152
+ for (const s of d.sauvegardes || [])
153
+ l(`sauvegarde ${s.nom} → ${jetons(s.fichier, valeurs)}`, s.commande);
154
+ for (const e of d.deploiements || [])
155
+ l(`déploiement ${e.titre || e.nom}`, e.commande);
156
+ for (const s of d.sante || [])
157
+ l(`santé ${s.nom}`, s.commande);
158
+ if (d.journaux)
159
+ l("journaux", d.journaux);
160
+ console.log(`\n${VERT(`✓ D4PF à blanc — rien n'a été sauvegardé ni déployé`)}`);
161
+ return 0;
162
+ }
163
+ pas(2, "sauvegardes");
164
+ for (const s of d.sauvegardes || []) {
165
+ const fichier = jetons(s.fichier, valeurs);
166
+ const chemin = isAbsolute(fichier) ? fichier : join(c.app, fichier);
167
+ mkdirSync(dirname(chemin), { recursive: true });
168
+ const r = spawnSync("bash", ["-c", jetons(s.commande, valeurs)], { cwd: c.app, env: process.env, maxBuffer: 4 * 1024 * 1024 * 1024 });
169
+ writeFileSync(chemin, r.stdout ?? Buffer.alloc(0));
170
+ const taille = existsSync(chemin) ? statSync(chemin).size : 0;
171
+ if (r.status !== 0 || !taille || (s.entete && debut(chemin, s.entete.length) !== s.entete)) {
172
+ console.error(`✗ ${basename(chemin)} : copie vide ou illisible (${s.nom})`);
173
+ return 1;
174
+ }
175
+ console.log(` ✓ ${basename(chemin)} — ${taille} octets`);
176
+ }
177
+ for (const [i, e] of (d.deploiements || []).entries()) {
178
+ pas(3 + Math.min(i, 1), String(e.titre || e.nom));
179
+ const r = shell(jetons(e.commande, valeurs), e.dossier === "racine" ? c.racine : c.app);
180
+ console.log(fin(r.sortie, e.lignes ?? 4));
181
+ if (r.code !== 0) {
182
+ console.error(`✗ déploiement « ${e.titre || e.nom} » en échec`);
183
+ return 1;
184
+ }
185
+ }
186
+ pas(5, "santé");
187
+ let malade = false;
188
+ for (const s of d.sante || []) {
189
+ const r = shell(jetons(s.commande, valeurs), c.app);
190
+ let h = null;
191
+ try {
192
+ h = JSON.parse(r.sortie);
193
+ }
194
+ catch { /* réponse illisible */ }
195
+ const bon = Boolean(h && h.ok && h.version === c.version && String(h.commit).startsWith(commit));
196
+ const plus = (s.champs || []).filter((k) => h?.[k] != null).map((k) => ` · ${k} ${h[k]}`).join("");
197
+ console.log(` ${bon ? "✓" : "✗"} ${s.nom} : ${h ? `${h.version} ${h.commit}${plus}` : "réponse illisible"}`);
198
+ if (!bon)
199
+ malade = true;
200
+ }
201
+ if (malade) {
202
+ console.error("✗ santé : version ou commit inattendu");
203
+ return 1;
204
+ }
205
+ pas(6, "journaux (dernières erreurs)");
206
+ if (d.journaux)
207
+ console.log(fin(shell(jetons(d.journaux, valeurs), c.app).sortie, 40));
208
+ console.log(`\n${VERT(`✓ D4PF terminé — ${c.nom} ${c.version} (${commit})`)}`);
209
+ return 0;
210
+ }
211
+ /** D4PFQ : D4PF puis D4Q — D4Q seulement si D4PF a réussi. SEULEMENT sur feu vert pour CETTE version. → code de sortie. */
212
+ export function d4pfq(argv) {
213
+ const a = d4pf(argv);
214
+ if (a !== 0) {
215
+ console.error("✗ D4PF en échec : D4Q non lancé");
216
+ return a;
217
+ }
218
+ // D4Q porte sur l'application déployée (celle de la config), jamais sur un autre dossier.
219
+ const b = d4q(argv.filter((x) => x.startsWith("--")));
220
+ if (b !== 0)
221
+ return b;
222
+ console.log(VERT(argv.includes("--a-blanc") ? "✓ D4PFQ à blanc — rien n'a été lancé" : "✓ D4PFQ terminé — déployé, puis la qualité"));
223
+ return 0;
224
+ }
225
+ //# sourceMappingURL=d4.js.map
package/dist/d4.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"d4.js","sourceRoot":"","sources":["../src/d4.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -42,6 +42,29 @@ export declare const afterEach: (fn: () => void | Promise<void>) => void;
42
42
  export declare function setDefaultTimeout(ms: number): void;
43
43
  /** Ne jouer que les cas portant l'une de ces étiquettes (les autres sont dits ignorés). Le CLI : `--tag=`. */
44
44
  export declare function setTagFilter(tags: string[]): void;
45
+ /** `mjs-unit rejouer <id>` : seuls ces essais (identifiant = premier mot du nom) sont joués ; les autres sont ignorés. */
46
+ export declare function setSeul(ids: string[]): void;
47
+ export interface JeuOptions<T> {
48
+ pour: string[];
49
+ construire: () => T | Promise<T>;
50
+ detruire?: (v: T) => void | Promise<void>;
51
+ }
52
+ export interface Jeu<T> {
53
+ readonly nom: string;
54
+ obtenir(): Promise<T>;
55
+ }
56
+ /**
57
+ * Un JEU DE DONNÉES partagé par plusieurs essais (un compte, puis une autorisation sur ce compte) : construit au premier
58
+ * `obtenir()`, gardé tant qu'un essai de `pour` n'a pas fini, détruit après le DERNIER. Un essai de `pour` qui ne s'exécute
59
+ * jamais est une anomalie relevée ; le jeu est alors détruit en fin de fichier. Un essai ignoré (filtre, rejouer) libère.
60
+ */
61
+ export declare function jeu<T>(nom: string, o: JeuOptions<T>): Jeu<T>;
62
+ /** Relève — et remet à zéro — le bilan des jeux de données (le CLI le porte au bloc `execution`). */
63
+ export declare function takeJeux(): {
64
+ construits: number;
65
+ detruits: number;
66
+ anomalies: string[];
67
+ };
45
68
  export declare function ok(cond: unknown, message?: string): void;
46
69
  export declare function equal(actual: unknown, expected: unknown, message?: string): void;
47
70
  export declare function deepEqual(actual: unknown, expected: unknown, message?: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}