guford-ui 0.1.0 → 0.2.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/bin.mjs +72 -27
- package/package.json +1 -1
package/bin.mjs
CHANGED
|
@@ -30,8 +30,9 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
30
30
|
const ROOT = resolve(__dirname, '..'); // racine du dépôt guford-ui (mode local)
|
|
31
31
|
const CONFIG_FILE = 'guford-ui.json';
|
|
32
32
|
|
|
33
|
-
//
|
|
34
|
-
const
|
|
33
|
+
// Dépôt GitHub par défaut (privé → lu via l'API Contents avec token).
|
|
34
|
+
const DEFAULT_REPO = 'bekmarc/guford-ui';
|
|
35
|
+
const DEFAULT_REF = 'main';
|
|
35
36
|
|
|
36
37
|
// --- couleurs ANSI ---------------------------------------------------------
|
|
37
38
|
const c = {
|
|
@@ -48,42 +49,72 @@ function fail(msg) {
|
|
|
48
49
|
process.exit(1);
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
// --- source du registry (local FS
|
|
52
|
+
// --- source du registry (local FS | URL statique | API GitHub privée) ------
|
|
52
53
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
54
|
+
* Résout la source du registry. 3 modes :
|
|
55
|
+
* - 'local' : fichiers du dépôt (exécution depuis quitus-ui/guford-ui)
|
|
56
|
+
* - 'url' : base HTTP statique (--registry / $GUFORD_UI_REGISTRY), token facultatif
|
|
57
|
+
* - 'github' : dépôt GitHub privé via l'API Contents (--repo/--ref + token requis)
|
|
55
58
|
*/
|
|
56
59
|
function resolveSource(flags) {
|
|
60
|
+
const token = flags.token || process.env.GUFORD_UI_TOKEN || process.env.GITHUB_TOKEN;
|
|
57
61
|
const explicit = flags.registry || process.env.GUFORD_UI_REGISTRY;
|
|
58
|
-
if (explicit) return {
|
|
59
|
-
if (existsSync(join(ROOT, 'registry.json'))) return {
|
|
60
|
-
return {
|
|
62
|
+
if (explicit) return { kind: 'url', base: explicit.replace(/\/+$/, ''), token };
|
|
63
|
+
if (!flags.repo && existsSync(join(ROOT, 'registry.json'))) return { kind: 'local', base: ROOT };
|
|
64
|
+
return { kind: 'github', repo: flags.repo || DEFAULT_REPO, ref: flags.ref || DEFAULT_REF, token };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function sourceUrl(source, rel) {
|
|
68
|
+
if (source.kind === 'url') return `${source.base}/${rel}`;
|
|
69
|
+
// GitHub Contents API : renvoie le contenu brut (texte + binaire) avec Accept: raw
|
|
70
|
+
return `https://api.github.com/repos/${source.repo}/contents/${rel}?ref=${source.ref}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function sourceHeaders(source) {
|
|
74
|
+
const h = { 'User-Agent': 'guford-ui-cli' };
|
|
75
|
+
if (source.kind === 'github') {
|
|
76
|
+
if (!source.token)
|
|
77
|
+
fail(
|
|
78
|
+
'Dépôt privé : un token est requis.\n' +
|
|
79
|
+
' → crée un PAT GitHub (Contents: read) puis: set GUFORD_UI_TOKEN=<token>\n' +
|
|
80
|
+
' (ou passe --token <token>, ou utilise --registry <url-publique>)',
|
|
81
|
+
);
|
|
82
|
+
h.Authorization = `Bearer ${source.token}`;
|
|
83
|
+
h.Accept = 'application/vnd.github.raw';
|
|
84
|
+
} else if (source.token) {
|
|
85
|
+
h.Authorization = `Bearer ${source.token}`;
|
|
86
|
+
}
|
|
87
|
+
return h;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function fetchEntry(source, rel) {
|
|
91
|
+
const url = sourceUrl(source, rel);
|
|
92
|
+
const res = await fetch(url, { headers: sourceHeaders(source) });
|
|
93
|
+
if (!res.ok) {
|
|
94
|
+
const hint = res.status === 404 ? ' (introuvable, ou token sans accès au dépôt privé)' : '';
|
|
95
|
+
fail(`Téléchargement échoué (${res.status})${hint} : ${url}`);
|
|
96
|
+
}
|
|
97
|
+
return Buffer.from(await res.arrayBuffer());
|
|
61
98
|
}
|
|
62
99
|
|
|
63
100
|
/** Lit un fichier texte du registry (chemin relatif à la racine, ex: 'registry.json'). */
|
|
64
101
|
async function readText(source, rel) {
|
|
65
|
-
if (source.
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return await res.text();
|
|
102
|
+
if (source.kind === 'local') {
|
|
103
|
+
const path = join(source.base, rel);
|
|
104
|
+
if (!existsSync(path)) fail(`Fichier introuvable: ${path}`);
|
|
105
|
+
return readFileSync(path, 'utf8');
|
|
70
106
|
}
|
|
71
|
-
|
|
72
|
-
if (!existsSync(path)) fail(`Fichier introuvable: ${path}`);
|
|
73
|
-
return readFileSync(path, 'utf8');
|
|
107
|
+
return (await fetchEntry(source, rel)).toString('utf8');
|
|
74
108
|
}
|
|
75
109
|
|
|
76
110
|
/** Lit un fichier (texte ou binaire) du registry → Buffer. */
|
|
77
111
|
async function readBuffer(source, rel) {
|
|
78
|
-
if (source.
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return Buffer.from(await res.arrayBuffer());
|
|
112
|
+
if (source.kind === 'local') {
|
|
113
|
+
const path = join(source.base, rel);
|
|
114
|
+
if (!existsSync(path)) fail(`Fichier introuvable: ${path}`);
|
|
115
|
+
return readFileSync(path);
|
|
83
116
|
}
|
|
84
|
-
|
|
85
|
-
if (!existsSync(path)) fail(`Fichier introuvable: ${path}`);
|
|
86
|
-
return readFileSync(path);
|
|
117
|
+
return await fetchEntry(source, rel);
|
|
87
118
|
}
|
|
88
119
|
|
|
89
120
|
async function loadRegistry(source) {
|
|
@@ -122,7 +153,10 @@ function loadProjectConfig(cwd) {
|
|
|
122
153
|
// --- parseur d'arguments ---------------------------------------------------
|
|
123
154
|
function parseArgs(argv) {
|
|
124
155
|
const positionals = [];
|
|
125
|
-
const flags = {
|
|
156
|
+
const flags = {
|
|
157
|
+
cwd: '.', dir: undefined, overwrite: false, dryRun: false,
|
|
158
|
+
registry: undefined, token: undefined, repo: undefined, ref: undefined,
|
|
159
|
+
};
|
|
126
160
|
for (let i = 0; i < argv.length; i++) {
|
|
127
161
|
const a = argv[i];
|
|
128
162
|
if (a === '--overwrite') flags.overwrite = true;
|
|
@@ -130,6 +164,9 @@ function parseArgs(argv) {
|
|
|
130
164
|
else if (a === '--cwd') flags.cwd = argv[++i];
|
|
131
165
|
else if (a === '--dir') flags.dir = argv[++i];
|
|
132
166
|
else if (a === '--registry') flags.registry = argv[++i];
|
|
167
|
+
else if (a === '--token') flags.token = argv[++i];
|
|
168
|
+
else if (a === '--repo') flags.repo = argv[++i];
|
|
169
|
+
else if (a === '--ref') flags.ref = argv[++i];
|
|
133
170
|
else if (a.startsWith('--')) fail(`Option inconnue: ${a}`);
|
|
134
171
|
else positionals.push(a);
|
|
135
172
|
}
|
|
@@ -137,7 +174,9 @@ function parseArgs(argv) {
|
|
|
137
174
|
}
|
|
138
175
|
|
|
139
176
|
function sourceLabel(source) {
|
|
140
|
-
|
|
177
|
+
if (source.kind === 'local') return c.dim('(registry local)');
|
|
178
|
+
if (source.kind === 'url') return c.dim(`(registry: ${source.base})`);
|
|
179
|
+
return c.dim(`(registry GitHub: ${source.repo}@${source.ref})`);
|
|
141
180
|
}
|
|
142
181
|
|
|
143
182
|
// --- commandes -------------------------------------------------------------
|
|
@@ -321,9 +360,15 @@ function help() {
|
|
|
321
360
|
${c.cyan('Options:')}
|
|
322
361
|
--cwd <path> Projet cible (défaut: .)
|
|
323
362
|
--dir <path> Racine d'installation (défaut: guford-ui.json puis src)
|
|
324
|
-
--registry <url> Base
|
|
363
|
+
--registry <url> Base HTTP statique du registry (sinon $GUFORD_UI_REGISTRY)
|
|
364
|
+
--repo <owner/repo> Dépôt GitHub (défaut: ${DEFAULT_REPO})
|
|
365
|
+
--ref <branch|tag> Réf GitHub (défaut: ${DEFAULT_REF}) — pin sur un tag pour reproductibilité
|
|
366
|
+
--token <token> Token GitHub pour dépôt privé (sinon $GUFORD_UI_TOKEN / $GITHUB_TOKEN)
|
|
325
367
|
--overwrite Écrase les fichiers existants
|
|
326
368
|
--dry-run Simule sans écrire
|
|
369
|
+
|
|
370
|
+
${c.cyan('Dépôt privé:')} crée un PAT GitHub (Contents: read), puis
|
|
371
|
+
${c.dim('set GUFORD_UI_TOKEN=<token> # Windows (cmd) | $env:GUFORD_UI_TOKEN="<token>" (PowerShell)')}
|
|
327
372
|
`);
|
|
328
373
|
}
|
|
329
374
|
|