@sia-ui/cli 0.5.0 → 0.6.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.
@@ -0,0 +1,111 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { empreinte } from "./lock.mjs";
4
+
5
+ /**
6
+ * La feuille commune, suivie comme un composant.
7
+ *
8
+ * Copiée une fois par `init`, puis plus rien ne la touchait : les composants
9
+ * se mettaient à jour sans elle. Or un composant peut dépendre d'une règle
10
+ * nouvelle de la feuille — le reset `box-sizing` en est un — et
11
+ * l'utilisateur recevait le composant sans ce qui le fait tenir.
12
+ *
13
+ * Son empreinte à la copie est notée dans le verrou (`styles`). Non
14
+ * retouchée, elle suit le registre ; retouchée, elle n'est remplacée que sur
15
+ * demande (`update --force`). Elle est lue à la même source que les
16
+ * composants : copie embarquée ou registre HTTP.
17
+ */
18
+
19
+ async function lire(chemin) {
20
+ try {
21
+ return await readFile(chemin);
22
+ } catch (error) {
23
+ if (error.code === "ENOENT") return null;
24
+ throw error;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * L'état de la feuille du projet.
30
+ *
31
+ * `absente`, `à jour`, `en retard` (non retouchée, le registre a plus
32
+ * récent), `modifiée` (retouchée depuis la copie), ou `non suivie` (copiée
33
+ * par une CLI qui ne notait pas son empreinte, et différente de l'actuelle).
34
+ */
35
+ export async function etatStyles({ cwd, config, lock, lireStyles }) {
36
+ const cible = join(cwd, config.styles);
37
+ const contenu = await lireStyles();
38
+ const actuelle = { contenu, empreinte: empreinte(contenu) };
39
+ const presente = await lire(cible);
40
+
41
+ if (presente === null) return { etat: "absente", cible, actuelle };
42
+
43
+ const locale = empreinte(presente);
44
+ if (locale === actuelle.empreinte) return { etat: "à jour", cible, actuelle };
45
+
46
+ const notee = lock.styles?.hash;
47
+ if (!notee) return { etat: "non suivie", cible, actuelle };
48
+ return {
49
+ etat: locale === notee ? "en retard" : "modifiée",
50
+ cible,
51
+ actuelle,
52
+ };
53
+ }
54
+
55
+ const RAISON = {
56
+ modifiée: "modifiée localement",
57
+ "non suivie": "copiée avant le suivi des versions",
58
+ };
59
+
60
+ /**
61
+ * Met la feuille à jour selon ce que la commande autorise, et le dit.
62
+ *
63
+ * - `creer` — `init` : seulement si elle est absente.
64
+ * - `sur` — `add` : absente ou en retard ; jamais une feuille retouchée.
65
+ * - `forcer` — `update --force` : même retouchée.
66
+ *
67
+ * Complète le verrou (`styles`) sans l'écrire : l'appelant l'écrit une fois,
68
+ * avec le reste. `dryRun` annonce sans rien toucher.
69
+ */
70
+ export async function synchroniserStyles(
71
+ { cwd, config, lock, lireStyles },
72
+ { mode = "sur", dryRun = false } = {},
73
+ ) {
74
+ const { etat, cible, actuelle } = await etatStyles({
75
+ cwd,
76
+ config,
77
+ lock,
78
+ lireStyles,
79
+ });
80
+
81
+ const noter = () => {
82
+ if (!dryRun) lock.styles = { file: config.styles, hash: actuelle.empreinte };
83
+ };
84
+
85
+ if (etat === "à jour") {
86
+ noter();
87
+ return { etat, action: "rien" };
88
+ }
89
+
90
+ const ecrire =
91
+ etat === "absente" ||
92
+ (mode !== "creer" && etat === "en retard") ||
93
+ mode === "forcer";
94
+
95
+ if (ecrire) {
96
+ if (!dryRun) {
97
+ await mkdir(dirname(cible), { recursive: true });
98
+ await writeFile(cible, actuelle.contenu);
99
+ }
100
+ noter();
101
+ console.log(`${etat === "absente" ? "add " : "update"} ${config.styles}`);
102
+ return { etat, action: "écrite" };
103
+ }
104
+
105
+ console.log(
106
+ mode === "creer"
107
+ ? `skip ${config.styles} (déjà présente — sia-ui update pour la mettre à jour)`
108
+ : `keep ${config.styles} (${RAISON[etat]} — sia-ui update --force pour la remplacer)`,
109
+ );
110
+ return { etat, action: "gardée" };
111
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sia-ui/cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Install SIA UI components progressively into an application.",
5
5
  "keywords": [
6
6
  "sia-ui",
@@ -39,10 +39,10 @@
39
39
  "react-dom": "^19.2.3",
40
40
  "typescript": "^5.9.3",
41
41
  "vitest": "^4.0.16",
42
- "@sia-ui/headless": "0.5.0",
43
- "@sia-ui/react": "0.5.0",
44
- "@sia-ui/tokens": "0.5.0",
45
- "@sia-ui/utils": "0.5.0"
42
+ "@sia-ui/headless": "0.6.0",
43
+ "@sia-ui/react": "0.6.0",
44
+ "@sia-ui/utils": "0.6.0",
45
+ "@sia-ui/tokens": "0.6.0"
46
46
  },
47
47
  "scripts": {
48
48
  "build": "node scripts/build.mjs",