synthesisui 0.16.250 → 0.16.251
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/dist/cli-flags.js +79 -0
- package/dist/commands/login.js +2 -1
- package/dist/commands/logout.js +26 -0
- package/dist/config.js +25 -1
- package/dist/index.js +15 -59
- package/package.json +1 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A LINHA DE COMANDO, DESMONTADA - e o único lugar que sabe fazer isso.
|
|
3
|
+
*
|
|
4
|
+
* Este parser vivia dentro do `index.ts`, privado, e por isso nunca foi
|
|
5
|
+
* exercido por um teste. O custo apareceu inteiro num defeito: `login --force`
|
|
6
|
+
* era lido de `args` - a lista de POSICIONAIS, de onde este parser já tirou
|
|
7
|
+
* toda `--flag` - então a flag anunciada no help nunca chegou ao comando, e a
|
|
8
|
+
* resposta era sugerir o comando que a pessoa acabou de rodar.
|
|
9
|
+
*
|
|
10
|
+
* Separado, ele é testável, e `boolFlag` fecha a porta: quem lê uma flag
|
|
11
|
+
* booleana pede pelo NOME dela a quem tem a resposta, e não procura a string
|
|
12
|
+
* numa lista que por construção não a contém.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* A REPEATED FLAG ACCUMULATES rather than overwriting.
|
|
16
|
+
*
|
|
17
|
+
* `--usage apps/web --usage apps/admin` is the natural way to say two, and keeping
|
|
18
|
+
* only the last would drop one silently - which is the failure mode this codebase
|
|
19
|
+
* refuses everywhere else. Every existing flag is passed once and still arrives as
|
|
20
|
+
* a string, so nothing that reads `typeof flags.x === "string"` changes.
|
|
21
|
+
*/
|
|
22
|
+
export function parseFlags(argv) {
|
|
23
|
+
const positionals = [];
|
|
24
|
+
const flags = {};
|
|
25
|
+
const put = (key, value) => {
|
|
26
|
+
const had = flags[key];
|
|
27
|
+
if (had === undefined) {
|
|
28
|
+
flags[key] = value;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (typeof value !== "string")
|
|
32
|
+
return;
|
|
33
|
+
flags[key] = [
|
|
34
|
+
...(Array.isArray(had) ? had : typeof had === "string" ? [had] : []),
|
|
35
|
+
value,
|
|
36
|
+
];
|
|
37
|
+
};
|
|
38
|
+
for (let i = 0; i < argv.length; i++) {
|
|
39
|
+
const arg = argv[i];
|
|
40
|
+
if (arg === "-h" || arg === "--help") {
|
|
41
|
+
flags.help = true;
|
|
42
|
+
}
|
|
43
|
+
else if (arg.startsWith("--")) {
|
|
44
|
+
const body = arg.slice(2);
|
|
45
|
+
const eq = body.indexOf("=");
|
|
46
|
+
if (eq !== -1) {
|
|
47
|
+
// `--key=value` form (e.g. --out=templates/page.tsx)
|
|
48
|
+
put(body.slice(0, eq), body.slice(eq + 1));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// `--key value` form
|
|
52
|
+
const next = argv[i + 1];
|
|
53
|
+
if (next !== undefined && !next.startsWith("--")) {
|
|
54
|
+
put(body, next);
|
|
55
|
+
i++;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
put(body, true);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
positionals.push(arg);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { positionals, flags };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* UMA FLAG BOOLEANA, LIDA PELO NOME - `true` só quando ela está mesmo lá.
|
|
70
|
+
*
|
|
71
|
+
* `--yes` sozinha chega como `true`; `--yes` seguida de um posicional chega
|
|
72
|
+
* como a string daquele posicional, porque o parser não sabe quais flags levam
|
|
73
|
+
* valor. Nos dois casos a pessoa DISSE a flag, e é isso que um booleano
|
|
74
|
+
* responde - tratar `--yes algo` como não-dito seria obedecer pela metade.
|
|
75
|
+
*/
|
|
76
|
+
export function boolFlag(flags, name) {
|
|
77
|
+
const v = flags[name];
|
|
78
|
+
return v === true || typeof v === "string" || Array.isArray(v);
|
|
79
|
+
}
|
package/dist/commands/login.js
CHANGED
|
@@ -53,7 +53,8 @@ export async function login(opts) {
|
|
|
53
53
|
if (existing && sameRegistry(existing.registry, base)) {
|
|
54
54
|
console.log("");
|
|
55
55
|
console.log(`✓ Already signed in to ${base} on this machine.`);
|
|
56
|
-
console.log(" Run `synthesisui login --force` to sign in as someone else
|
|
56
|
+
console.log(" Run `synthesisui login --force` to sign in as someone else,");
|
|
57
|
+
console.log(" or `synthesisui logout` to sign out of this machine.");
|
|
57
58
|
return;
|
|
58
59
|
}
|
|
59
60
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { clearCredentials, credentialsPath, readCredentials, } from "../config.js";
|
|
2
|
+
/**
|
|
3
|
+
* SAIR DA CONTA NESTA MÁQUINA - o comando que faltava do par.
|
|
4
|
+
*
|
|
5
|
+
* O CLI sabia entrar e não sabia sair. Quem precisava trocar de conta era
|
|
6
|
+
* mandado apagar `~/.synthesisui/credentials.json` na mão - e uma instrução que
|
|
7
|
+
* termina em `rm` num diretório de configuração é a que faz alguém apagar a
|
|
8
|
+
* pasta errada.
|
|
9
|
+
*
|
|
10
|
+
* Ele diz de QUAL host saiu, porque a credencial guarda o registry que a
|
|
11
|
+
* emitiu: sair de um localhost e achar que saiu da produção é o mesmo mal
|
|
12
|
+
* entendido que fez o token de dev ser enviado para o site em 31/07.
|
|
13
|
+
*/
|
|
14
|
+
export async function logout() {
|
|
15
|
+
const existing = await readCredentials();
|
|
16
|
+
const had = await clearCredentials();
|
|
17
|
+
console.log("");
|
|
18
|
+
if (!had) {
|
|
19
|
+
console.log("✓ You are not signed in on this machine - nothing to do.");
|
|
20
|
+
console.log(" Run `synthesisui login` to connect the CLI to an account.");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
console.log(`✓ Signed out${existing?.registry ? ` of ${existing.registry}` : ""} on this machine.`);
|
|
24
|
+
console.log(` Removed ${credentialsPath}`);
|
|
25
|
+
console.log(" Run `synthesisui login` to sign in as someone else.");
|
|
26
|
+
}
|
package/dist/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
1
|
+
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
/**
|
|
@@ -76,6 +76,30 @@ export async function writeToken(token, registry) {
|
|
|
76
76
|
mode: 0o600,
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* SAIR DA MÁQUINA - o outro lado da porta que o `login` abre.
|
|
81
|
+
*
|
|
82
|
+
* Existir era o mínimo: até aqui a única forma de encerrar a sessão era apagar
|
|
83
|
+
* `~/.synthesisui/credentials.json` à mão, e um produto que só sabe entrar
|
|
84
|
+
* obriga a pessoa a mexer no disco para trocar de conta.
|
|
85
|
+
*
|
|
86
|
+
* O arquivo inteiro vai embora, e não só o campo `token`: um arquivo sem token
|
|
87
|
+
* é indistinguível de nenhum arquivo para quem lê (`readCredentials` devolve
|
|
88
|
+
* `null` nos dois casos) e ainda deixaria o host da sessão antiga gravado.
|
|
89
|
+
*
|
|
90
|
+
* Devolve `false` quando não havia nada - a diferença entre "saí" e "você já
|
|
91
|
+
* estava fora" é a única coisa que o comando tem para dizer.
|
|
92
|
+
*/
|
|
93
|
+
export async function clearCredentials() {
|
|
94
|
+
const existing = await readCredentials();
|
|
95
|
+
try {
|
|
96
|
+
await rm(credentialsPath, { force: true });
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// já não existe, ou o disco recusou - o estado final é o mesmo
|
|
100
|
+
}
|
|
101
|
+
return existing !== null;
|
|
102
|
+
}
|
|
79
103
|
/** Project-level config (committed): `<root>/_synthesisui/config.json`. */
|
|
80
104
|
export const DEFAULT_CONFIG = {
|
|
81
105
|
target: "next",
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
+
import { boolFlag, parseFlags } from "./cli-flags.js";
|
|
4
5
|
import { absorb } from "./commands/absorb.js";
|
|
5
6
|
import { add } from "./commands/add.js";
|
|
6
7
|
import { adopt } from "./commands/adopt.js";
|
|
@@ -18,6 +19,7 @@ import { runImport } from "./commands/import.js";
|
|
|
18
19
|
import { init } from "./commands/init.js";
|
|
19
20
|
import { list } from "./commands/list.js";
|
|
20
21
|
import { login } from "./commands/login.js";
|
|
22
|
+
import { logout } from "./commands/logout.js";
|
|
21
23
|
import { mcp } from "./commands/mcp.js";
|
|
22
24
|
import { refit } from "./commands/refit.js";
|
|
23
25
|
import { request } from "./commands/request.js";
|
|
@@ -37,6 +39,7 @@ const HELP = `synthesisui - bring SynthesisUI design systems into your project
|
|
|
37
39
|
|
|
38
40
|
Usage - deterministic, FREE:
|
|
39
41
|
synthesisui login [options] connect the CLI to your account (device-flow; --force to switch accounts)
|
|
42
|
+
synthesisui logout sign out of this machine (removes the saved token)
|
|
40
43
|
synthesisui init [options] write _synthesisui/config.json (target, dirs); --ds to bring one in
|
|
41
44
|
synthesisui list [options] list the published design systems
|
|
42
45
|
synthesisui list --mine your own systems, with their group
|
|
@@ -135,61 +138,6 @@ Examples:
|
|
|
135
138
|
synthesisui advise "habit-building app for tracking personal finances"
|
|
136
139
|
synthesisui generate "an upgrade banner with a title, message and a primary CTA"
|
|
137
140
|
`;
|
|
138
|
-
/** Extracts simple `--flag value` pairs and the remaining positionals. */
|
|
139
|
-
/**
|
|
140
|
-
* A REPEATED FLAG ACCUMULATES rather than overwriting.
|
|
141
|
-
*
|
|
142
|
-
* `--usage apps/web --usage apps/admin` is the natural way to say two, and keeping
|
|
143
|
-
* only the last would drop one silently - which is the failure mode this codebase
|
|
144
|
-
* refuses everywhere else. Every existing flag is passed once and still arrives as
|
|
145
|
-
* a string, so nothing that reads `typeof flags.x === "string"` changes.
|
|
146
|
-
*/
|
|
147
|
-
function parseFlags(argv) {
|
|
148
|
-
const positionals = [];
|
|
149
|
-
const flags = {};
|
|
150
|
-
const put = (key, value) => {
|
|
151
|
-
const had = flags[key];
|
|
152
|
-
if (had === undefined) {
|
|
153
|
-
flags[key] = value;
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
if (typeof value !== "string")
|
|
157
|
-
return;
|
|
158
|
-
flags[key] = [
|
|
159
|
-
...(Array.isArray(had) ? had : typeof had === "string" ? [had] : []),
|
|
160
|
-
value,
|
|
161
|
-
];
|
|
162
|
-
};
|
|
163
|
-
for (let i = 0; i < argv.length; i++) {
|
|
164
|
-
const arg = argv[i];
|
|
165
|
-
if (arg === "-h" || arg === "--help") {
|
|
166
|
-
flags.help = true;
|
|
167
|
-
}
|
|
168
|
-
else if (arg.startsWith("--")) {
|
|
169
|
-
const body = arg.slice(2);
|
|
170
|
-
const eq = body.indexOf("=");
|
|
171
|
-
if (eq !== -1) {
|
|
172
|
-
// `--key=value` form (e.g. --out=templates/page.tsx)
|
|
173
|
-
put(body.slice(0, eq), body.slice(eq + 1));
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
// `--key value` form
|
|
177
|
-
const next = argv[i + 1];
|
|
178
|
-
if (next !== undefined && !next.startsWith("--")) {
|
|
179
|
-
put(body, next);
|
|
180
|
-
i++;
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
put(body, true);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
positionals.push(arg);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return { positionals, flags };
|
|
192
|
-
}
|
|
193
141
|
async function main() {
|
|
194
142
|
const { positionals, flags } = parseFlags(process.argv.slice(2));
|
|
195
143
|
const [command, ...args] = positionals;
|
|
@@ -397,11 +345,19 @@ async function main() {
|
|
|
397
345
|
await add(slug, { registry, dir, version, cli: CLI_VERSION });
|
|
398
346
|
break;
|
|
399
347
|
}
|
|
348
|
+
case "logout":
|
|
349
|
+
/**
|
|
350
|
+
* O outro lado do `login`. Sem ele a única saída era apagar
|
|
351
|
+
* `~/.synthesisui/credentials.json` à mão - e trocar de conta é o
|
|
352
|
+
* caminho normal de quem testa a plataforma em mais de um repositório.
|
|
353
|
+
*/
|
|
354
|
+
await logout();
|
|
355
|
+
break;
|
|
400
356
|
case "login":
|
|
401
357
|
// `--force` porque o comando agora sai cedo quando esta máquina já tem
|
|
402
358
|
// sessão para este host - trocar de conta continua possível, e passa a
|
|
403
359
|
// ser dito em vez de ser o comportamento padrão.
|
|
404
|
-
await login({ registry, force:
|
|
360
|
+
await login({ registry, force: boolFlag(flags, "force") });
|
|
405
361
|
break;
|
|
406
362
|
case "init": {
|
|
407
363
|
const target = typeof flags.target === "string" ? flags.target : undefined;
|
|
@@ -562,10 +518,10 @@ async function main() {
|
|
|
562
518
|
dir,
|
|
563
519
|
registry,
|
|
564
520
|
cli: CLI_VERSION,
|
|
565
|
-
recordOnly:
|
|
566
|
-
yes:
|
|
521
|
+
recordOnly: boolFlag(flags, "record-only"),
|
|
522
|
+
yes: boolFlag(flags, "yes"),
|
|
567
523
|
/** `--full`: o relatório inteiro do leitor. Por padrão a re-medição conta o que MUDOU. */
|
|
568
|
-
full:
|
|
524
|
+
full: boolFlag(flags, "full"),
|
|
569
525
|
});
|
|
570
526
|
break;
|
|
571
527
|
/**
|
package/package.json
CHANGED