expxdev 0.2.0 → 0.4.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/dist/cli/expx.d.ts +2 -0
- package/dist/cli/expx.js +69 -11
- package/dist/cli/expx.js.map +1 -1
- package/dist/cli/perguntar.d.ts +75 -0
- package/dist/cli/perguntar.js +179 -0
- package/dist/cli/perguntar.js.map +1 -0
- package/dist/cli/visual.d.ts +30 -0
- package/dist/cli/visual.js +73 -0
- package/dist/cli/visual.js.map +1 -0
- package/dist/cli/wizard.d.ts +27 -0
- package/dist/cli/wizard.js +167 -0
- package/dist/cli/wizard.js.map +1 -0
- package/package.json +3 -2
- package/ui/dist/assets/index-BIlVg-33.js +14 -0
- package/ui/dist/index.html +1 -1
- package/ui/dist/assets/index-BNE_RJrV.js +0 -15
package/dist/cli/expx.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Perguntador } from "./perguntar.js";
|
|
1
2
|
/**
|
|
2
3
|
* O entrypoint do binário `expx`.
|
|
3
4
|
*
|
|
@@ -10,4 +11,5 @@ export type Saida = {
|
|
|
10
11
|
escreverErro?: (texto: string) => void;
|
|
11
12
|
};
|
|
12
13
|
export type Executor = (resto: readonly string[], saida: Required<Saida>) => Promise<number>;
|
|
14
|
+
export declare function usarPerguntador(fabrica: () => Perguntador): void;
|
|
13
15
|
export declare function executarExpx(argv: readonly string[], saida?: Saida): Promise<number>;
|
package/dist/cli/expx.js
CHANGED
|
@@ -6,8 +6,38 @@ import { adicionarSkills, removerSkills } from "./selecionar.js";
|
|
|
6
6
|
import { interpretarFlagsUpdate, executarUpdate } from "../update/flags.js";
|
|
7
7
|
import { diagnosticar } from "../doctor/verificadores.js";
|
|
8
8
|
import { avaliarSelecao } from "./selecao.js";
|
|
9
|
+
import { executarWizard } from "./wizard.js";
|
|
10
|
+
import { perguntadorDeTerminal } from "./perguntar.js";
|
|
11
|
+
import { NOMES } from "../nucleo/catalogo.js";
|
|
12
|
+
import { hero, sucesso, temCor } from "./visual.js";
|
|
13
|
+
import { versaoDoCli } from "../nucleo/lock.js";
|
|
9
14
|
import { instalarPlugin } from "../harness/instalar.js";
|
|
10
15
|
import { join } from "node:path";
|
|
16
|
+
/**
|
|
17
|
+
* Há um humano capaz de responder?
|
|
18
|
+
*
|
|
19
|
+
* Precisa dos DOIS lados: `stdout` sozinho não basta, porque escrever no
|
|
20
|
+
* terminal não prova que existe teclado do outro lado — num `expx init < /dev/null`
|
|
21
|
+
* o `stdout` continua TTY e o wizard travaria esperando uma resposta que não vem.
|
|
22
|
+
* É `stdin` que decide se dá para perguntar.
|
|
23
|
+
*/
|
|
24
|
+
function ehInterativo() {
|
|
25
|
+
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
26
|
+
}
|
|
27
|
+
/** Injetável para o teste trocar o terminal por um roteiro de respostas. */
|
|
28
|
+
let criarPerguntador = () => perguntadorDeTerminal();
|
|
29
|
+
export function usarPerguntador(fabrica) {
|
|
30
|
+
criarPerguntador = fabrica;
|
|
31
|
+
}
|
|
32
|
+
function comoEscolherSkills() {
|
|
33
|
+
return [
|
|
34
|
+
"escolha as skills com --skills, ou rode num terminal para responder na hora:",
|
|
35
|
+
"",
|
|
36
|
+
` npx expxdev init --skills ${NOMES.slice(0, 2).join(",")} --yes`,
|
|
37
|
+
"",
|
|
38
|
+
`disponiveis: ${NOMES.join(", ")}`,
|
|
39
|
+
].join("\n");
|
|
40
|
+
}
|
|
11
41
|
const EXECUTORES = {
|
|
12
42
|
panel: async (resto) => principalPainel(resto),
|
|
13
43
|
init: async (resto, saida) => {
|
|
@@ -16,36 +46,64 @@ const EXECUTORES = {
|
|
|
16
46
|
saida.escreverErro(`${f.erro}\n`);
|
|
17
47
|
return 1;
|
|
18
48
|
}
|
|
19
|
-
|
|
49
|
+
let opcoes = f.opcoes;
|
|
50
|
+
// Faltou o que instalar e há alguém para responder? Pergunta, em vez de
|
|
51
|
+
// sair com "nenhuma skill selecionada" — que era o beco sem saída do
|
|
52
|
+
// `npx expxdev init` puro.
|
|
53
|
+
if (opcoes.skills.length === 0 && ehInterativo()) {
|
|
54
|
+
saida.escrever(hero(versaoDoCli()));
|
|
55
|
+
const p = criarPerguntador();
|
|
56
|
+
try {
|
|
57
|
+
const w = await executarWizard(p, opcoes, process.cwd());
|
|
58
|
+
if (!w.ok) {
|
|
59
|
+
saida.escreverErro(`${w.erro}\n`);
|
|
60
|
+
return 1;
|
|
61
|
+
}
|
|
62
|
+
opcoes = w.opcoes;
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
p.fechar();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const aval = avaliarSelecao(opcoes.skills);
|
|
20
69
|
if (!aval.permitido) {
|
|
21
70
|
saida.escreverErro(`${aval.erros.join("\n")}\n`);
|
|
71
|
+
// Sem terminal para perguntar, a saída precisa dizer como resolver:
|
|
72
|
+
// o erro sozinho não ensina a próxima ação.
|
|
73
|
+
if (!ehInterativo())
|
|
74
|
+
saida.escreverErro(`\n${comoEscolherSkills()}\n`);
|
|
22
75
|
return 1;
|
|
23
76
|
}
|
|
24
77
|
for (const a of aval.avisos)
|
|
25
78
|
saida.escrever(`aviso: ${a}\n`);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
saida.escrever(`instalaria: ${f.opcoes.skills.join(", ")}\nuse --yes para aplicar sem perguntar\n`);
|
|
79
|
+
if (!opcoes.sim && !ehInterativo()) {
|
|
80
|
+
saida.escrever(`instalaria: ${opcoes.skills.join(", ")}\nuse --yes para aplicar sem perguntar\n`);
|
|
29
81
|
return 0;
|
|
30
82
|
}
|
|
31
|
-
const harness =
|
|
32
|
-
const r = await executarInit({ raiz: process.cwd(), skills:
|
|
83
|
+
const harness = opcoes.harness.length > 0 ? opcoes.harness : ["claude"];
|
|
84
|
+
const r = await executarInit({ raiz: process.cwd(), skills: opcoes.skills, harness });
|
|
33
85
|
for (const a of r.avisos)
|
|
34
86
|
saida.escrever(`aviso: ${a}\n`);
|
|
35
87
|
for (const x of r.falhas)
|
|
36
88
|
saida.escreverErro(`falhou ${x.nome}: ${x.erro}\n`);
|
|
37
89
|
if (!r.ok)
|
|
38
90
|
return 1;
|
|
39
|
-
|
|
91
|
+
const fecho = [`instaladas: ${r.instaladas.join(", ")}`];
|
|
40
92
|
if (harness.includes("claude")) {
|
|
41
93
|
const inst = await instalarPlugin(join(process.cwd(), ".expx", "marketplace"));
|
|
42
|
-
if (inst.instrucao !== undefined)
|
|
94
|
+
if (inst.instrucao !== undefined) {
|
|
95
|
+
saida.escrever(sucesso(fecho, temCor()));
|
|
43
96
|
saida.escrever(`\n${inst.instrucao}\n`);
|
|
44
|
-
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
if (inst.erro !== undefined) {
|
|
100
|
+
saida.escrever(sucesso(fecho, temCor()));
|
|
45
101
|
saida.escreverErro(`nao foi possivel registrar o plugin: ${inst.erro}\n`);
|
|
46
|
-
|
|
47
|
-
|
|
102
|
+
return 0;
|
|
103
|
+
}
|
|
104
|
+
fecho.push("plugin registrado: os comandos /expx: estao disponiveis");
|
|
48
105
|
}
|
|
106
|
+
saida.escrever(sucesso(fecho, temCor()));
|
|
49
107
|
return 0;
|
|
50
108
|
},
|
|
51
109
|
add: async (resto, saida) => {
|
package/dist/cli/expx.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expx.js","sourceRoot":"","sources":["../../src/cli/expx.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAmB,MAAM,kBAAkB,CAAC;AACtF,OAAO,EAAE,SAAS,IAAI,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAiBjC,MAAM,UAAU,GAA0C;IACxD,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC;IAE9C,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC3B,MAAM,CAAC,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACV,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;YAClC,OAAO,CAAC,CAAC;QACX,CAAC;
|
|
1
|
+
{"version":3,"file":"expx.js","sourceRoot":"","sources":["../../src/cli/expx.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Readable, Writable } from "node:stream";
|
|
2
|
+
/**
|
|
3
|
+
* A camada de pergunta e resposta do terminal — e só ela.
|
|
4
|
+
*
|
|
5
|
+
* O wizard do `init` não fala com `process.stdin`: recebe um `Perguntador`.
|
|
6
|
+
* É o que torna o fluxo testável sem subprocesso e sem TTY falso, do mesmo
|
|
7
|
+
* jeito que `expx.ts` já injeta a saída para não capturar `process.stdout`
|
|
8
|
+
* global.
|
|
9
|
+
*
|
|
10
|
+
* `marcar` é opcional de propósito. Ele existe quando o terminal navega, e
|
|
11
|
+
* some quando não navega — e é essa ausência que faz o wizard cair sozinho
|
|
12
|
+
* para a escolha por número, sem precisar perguntar duas vezes "dá para
|
|
13
|
+
* navegar aqui?".
|
|
14
|
+
*/
|
|
15
|
+
export type Item = {
|
|
16
|
+
valor: string;
|
|
17
|
+
rotulo: string;
|
|
18
|
+
marcado?: boolean;
|
|
19
|
+
};
|
|
20
|
+
export type Marcacao = {
|
|
21
|
+
titulo: string;
|
|
22
|
+
itens: readonly Item[];
|
|
23
|
+
};
|
|
24
|
+
export type Perguntador = {
|
|
25
|
+
/** Uma linha de texto livre, já sem espaço nas pontas. */
|
|
26
|
+
linha: (rotulo: string) => Promise<string>;
|
|
27
|
+
/** Sim ou não. */
|
|
28
|
+
confirmar: (rotulo: string, padrao: boolean) => Promise<boolean>;
|
|
29
|
+
/** Navegar e marcar. Ausente quando o terminal não suporta. `undefined` = cancelou. */
|
|
30
|
+
marcar?: (m: Marcacao) => Promise<string[] | undefined>;
|
|
31
|
+
escrever: (texto: string) => void;
|
|
32
|
+
fechar: () => void;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Dá para desenhar um menu navegável aqui?
|
|
36
|
+
*
|
|
37
|
+
* Exige os dois lados do terminal: sem `stdin` não há setas para ler, e sem
|
|
38
|
+
* `stdout` não há onde redesenhar a lista a cada tecla. `TERM=dumb` anuncia
|
|
39
|
+
* explicitamente um terminal sem controle de cursor.
|
|
40
|
+
*/
|
|
41
|
+
export declare function podeNavegar(entrada?: Readable & {
|
|
42
|
+
isTTY?: boolean;
|
|
43
|
+
}, saida?: Writable & {
|
|
44
|
+
isTTY?: boolean;
|
|
45
|
+
}, env?: NodeJS.ProcessEnv): boolean;
|
|
46
|
+
export declare function perguntadorDeTerminal(entrada?: Readable & {
|
|
47
|
+
isTTY?: boolean;
|
|
48
|
+
}, saida?: Writable & {
|
|
49
|
+
isTTY?: boolean;
|
|
50
|
+
}): Perguntador;
|
|
51
|
+
/**
|
|
52
|
+
* Um perguntador de roteiro, para teste: consome respostas em ordem.
|
|
53
|
+
*
|
|
54
|
+
* Acabaram as respostas? Devolve string vazia — que todo passo trata como
|
|
55
|
+
* "aceito o padrão". Um teste que esquece uma resposta termina com o padrão
|
|
56
|
+
* em vez de travar o processo esperando `stdin`.
|
|
57
|
+
*
|
|
58
|
+
* Por padrão NÃO navega, porque o roteiro testa o caminho por número. Passe
|
|
59
|
+
* `marcacoes` para testar o caminho navegável: cada entrada é o que a pessoa
|
|
60
|
+
* teria marcado naquele menu.
|
|
61
|
+
*/
|
|
62
|
+
export declare function perguntadorDeRoteiro(respostas: readonly string[], marcacoes?: readonly (readonly string[] | undefined)[]): Perguntador & {
|
|
63
|
+
escrito: () => string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Lê uma escolha múltipla por número: `1,3` ou `1 3`.
|
|
67
|
+
*
|
|
68
|
+
* Devolve `undefined` quando algum número está fora da faixa, para o chamador
|
|
69
|
+
* repetir a pergunta em vez de instalar a coisa errada em silêncio. Resposta
|
|
70
|
+
* vazia é escolha vazia — quem decide se isso vale é a regra de seleção, não
|
|
71
|
+
* a leitura.
|
|
72
|
+
*/
|
|
73
|
+
export declare function interpretarEscolhaMultipla(resposta: string, total: number): number[] | undefined;
|
|
74
|
+
/** `sim`/`s`/`y`/`yes` é sim; vazio devolve o padrão; o resto é não. */
|
|
75
|
+
export declare function interpretarSimNao(resposta: string, padrao: boolean): boolean;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { createInterface } from "node:readline";
|
|
2
|
+
import { checkbox, confirm } from "@inquirer/prompts";
|
|
3
|
+
import { pintar, temCor } from "./visual.js";
|
|
4
|
+
/**
|
|
5
|
+
* Dá para desenhar um menu navegável aqui?
|
|
6
|
+
*
|
|
7
|
+
* Exige os dois lados do terminal: sem `stdin` não há setas para ler, e sem
|
|
8
|
+
* `stdout` não há onde redesenhar a lista a cada tecla. `TERM=dumb` anuncia
|
|
9
|
+
* explicitamente um terminal sem controle de cursor.
|
|
10
|
+
*/
|
|
11
|
+
export function podeNavegar(entrada = process.stdin, saida = process.stdout, env = process.env) {
|
|
12
|
+
if (env["TERM"] === "dumb")
|
|
13
|
+
return false;
|
|
14
|
+
if (env["EXPX_SEM_NAVEGACAO"] === "1")
|
|
15
|
+
return false;
|
|
16
|
+
return entrada.isTTY === true && saida.isTTY === true;
|
|
17
|
+
}
|
|
18
|
+
function cancelou(e) {
|
|
19
|
+
return e instanceof Error && (e.name === "ExitPromptError" || e.name === "AbortPromptError");
|
|
20
|
+
}
|
|
21
|
+
export function perguntadorDeTerminal(entrada = process.stdin, saida = process.stdout) {
|
|
22
|
+
let rl;
|
|
23
|
+
const obter = () => {
|
|
24
|
+
rl ??= createInterface({ input: entrada, output: saida });
|
|
25
|
+
return rl;
|
|
26
|
+
};
|
|
27
|
+
// O readline próprio e o inquirer não podem estar abertos ao mesmo tempo:
|
|
28
|
+
// os dois leem o mesmo `stdin` e disputariam cada tecla. Fechar o nosso
|
|
29
|
+
// antes de entregar o terminal ao inquirer evita a disputa.
|
|
30
|
+
const semReadline = async (acao) => {
|
|
31
|
+
rl?.close();
|
|
32
|
+
rl = undefined;
|
|
33
|
+
return acao();
|
|
34
|
+
};
|
|
35
|
+
const navegavel = podeNavegar(entrada, saida);
|
|
36
|
+
const base = {
|
|
37
|
+
linha: async (rotulo) => {
|
|
38
|
+
const resposta = await new Promise((resolver) => {
|
|
39
|
+
obter().question(rotulo, resolver);
|
|
40
|
+
});
|
|
41
|
+
return resposta.trim();
|
|
42
|
+
},
|
|
43
|
+
confirmar: async (rotulo, padrao) => {
|
|
44
|
+
if (!navegavel) {
|
|
45
|
+
const r = await base.linha(`${rotulo} ${padrao ? "[S/n]" : "[s/N]"} `);
|
|
46
|
+
return interpretarSimNao(r, padrao);
|
|
47
|
+
}
|
|
48
|
+
return semReadline(() => confirm({
|
|
49
|
+
message: rotulo,
|
|
50
|
+
default: padrao,
|
|
51
|
+
theme: {
|
|
52
|
+
// O inquirer responde "Yes"/"No" e sugere "(y/N)". Traduzir as
|
|
53
|
+
// palavras-chave muda as duas coisas de uma vez: a dica vira
|
|
54
|
+
// "(s/n)" e o "s" que a pessoa digita passa a ser reconhecido —
|
|
55
|
+
// o parser compara a tecla com a inicial destas palavras.
|
|
56
|
+
keywords: { yes: "sim", no: "nao" },
|
|
57
|
+
prefix: pintar("?", "azulClaro", temCor()),
|
|
58
|
+
},
|
|
59
|
+
}));
|
|
60
|
+
},
|
|
61
|
+
escrever: (texto) => {
|
|
62
|
+
saida.write(texto);
|
|
63
|
+
},
|
|
64
|
+
fechar: () => {
|
|
65
|
+
rl?.close();
|
|
66
|
+
rl = undefined;
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
if (!navegavel)
|
|
70
|
+
return base;
|
|
71
|
+
return {
|
|
72
|
+
...base,
|
|
73
|
+
marcar: async (m) => semReadline(async () => {
|
|
74
|
+
try {
|
|
75
|
+
return await checkbox({
|
|
76
|
+
message: m.titulo,
|
|
77
|
+
choices: m.itens.map((i) => ({
|
|
78
|
+
name: i.rotulo,
|
|
79
|
+
value: i.valor,
|
|
80
|
+
checked: i.marcado ?? false,
|
|
81
|
+
})),
|
|
82
|
+
theme: {
|
|
83
|
+
icon: {
|
|
84
|
+
checked: pintar("◉", "azulClaro", temCor()),
|
|
85
|
+
unchecked: pintar("◯", "cinza", temCor()),
|
|
86
|
+
cursor: pintar("❯", "azulClaro", temCor()),
|
|
87
|
+
},
|
|
88
|
+
style: {
|
|
89
|
+
// A dica de teclas em portugues: o padrao do inquirer é em
|
|
90
|
+
// ingles, e o resto do CLI inteiro fala portugues.
|
|
91
|
+
keysHelpTip: () => pintar("setas navegam · espaco marca · enter confirma", "cinza", temCor()),
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
// O menu inteiro cabe na tela: a lista tem seis itens e rolar
|
|
95
|
+
// esconderia justamente a comparação entre elas.
|
|
96
|
+
pageSize: Math.max(m.itens.length, 6),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
if (cancelou(e))
|
|
101
|
+
return undefined;
|
|
102
|
+
throw e;
|
|
103
|
+
}
|
|
104
|
+
}),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Um perguntador de roteiro, para teste: consome respostas em ordem.
|
|
109
|
+
*
|
|
110
|
+
* Acabaram as respostas? Devolve string vazia — que todo passo trata como
|
|
111
|
+
* "aceito o padrão". Um teste que esquece uma resposta termina com o padrão
|
|
112
|
+
* em vez de travar o processo esperando `stdin`.
|
|
113
|
+
*
|
|
114
|
+
* Por padrão NÃO navega, porque o roteiro testa o caminho por número. Passe
|
|
115
|
+
* `marcacoes` para testar o caminho navegável: cada entrada é o que a pessoa
|
|
116
|
+
* teria marcado naquele menu.
|
|
117
|
+
*/
|
|
118
|
+
export function perguntadorDeRoteiro(respostas, marcacoes) {
|
|
119
|
+
const restantes = [...respostas];
|
|
120
|
+
const marcadas = marcacoes === undefined ? undefined : [...marcacoes];
|
|
121
|
+
let escrito = "";
|
|
122
|
+
const p = {
|
|
123
|
+
linha: (rotulo) => {
|
|
124
|
+
escrito += rotulo;
|
|
125
|
+
return Promise.resolve(restantes.shift() ?? "");
|
|
126
|
+
},
|
|
127
|
+
confirmar: (rotulo, padrao) => {
|
|
128
|
+
escrito += rotulo;
|
|
129
|
+
const r = restantes.shift();
|
|
130
|
+
return Promise.resolve(r === undefined || r === "" ? padrao : interpretarSimNao(r, padrao));
|
|
131
|
+
},
|
|
132
|
+
escrever: (texto) => {
|
|
133
|
+
escrito += texto;
|
|
134
|
+
},
|
|
135
|
+
fechar: () => { },
|
|
136
|
+
escrito: () => escrito,
|
|
137
|
+
};
|
|
138
|
+
if (marcadas !== undefined) {
|
|
139
|
+
p.marcar = (m) => {
|
|
140
|
+
escrito += m.titulo;
|
|
141
|
+
for (const i of m.itens)
|
|
142
|
+
escrito += `\n${i.rotulo}`;
|
|
143
|
+
const proxima = marcadas.shift();
|
|
144
|
+
return Promise.resolve(proxima === undefined ? [] : [...proxima]);
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
return p;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Lê uma escolha múltipla por número: `1,3` ou `1 3`.
|
|
151
|
+
*
|
|
152
|
+
* Devolve `undefined` quando algum número está fora da faixa, para o chamador
|
|
153
|
+
* repetir a pergunta em vez de instalar a coisa errada em silêncio. Resposta
|
|
154
|
+
* vazia é escolha vazia — quem decide se isso vale é a regra de seleção, não
|
|
155
|
+
* a leitura.
|
|
156
|
+
*/
|
|
157
|
+
export function interpretarEscolhaMultipla(resposta, total) {
|
|
158
|
+
if (resposta.trim() === "")
|
|
159
|
+
return [];
|
|
160
|
+
const indices = [];
|
|
161
|
+
for (const parte of resposta.split(/[,\s]+/).filter((p) => p !== "")) {
|
|
162
|
+
if (!/^\d+$/.test(parte))
|
|
163
|
+
return undefined;
|
|
164
|
+
const n = Number(parte);
|
|
165
|
+
if (n < 1 || n > total)
|
|
166
|
+
return undefined;
|
|
167
|
+
if (!indices.includes(n - 1))
|
|
168
|
+
indices.push(n - 1);
|
|
169
|
+
}
|
|
170
|
+
return indices;
|
|
171
|
+
}
|
|
172
|
+
/** `sim`/`s`/`y`/`yes` é sim; vazio devolve o padrão; o resto é não. */
|
|
173
|
+
export function interpretarSimNao(resposta, padrao) {
|
|
174
|
+
const v = resposta.trim().toLowerCase();
|
|
175
|
+
if (v === "")
|
|
176
|
+
return padrao;
|
|
177
|
+
return v === "s" || v === "sim" || v === "y" || v === "yes";
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=perguntar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perguntar.js","sourceRoot":"","sources":["../../src/cli/perguntar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAkB,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAsC7C;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,UAA0C,OAAO,CAAC,KAAK,EACvD,QAAwC,OAAO,CAAC,MAAM,EACtD,MAAyB,OAAO,CAAC,GAAG;IAEpC,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,GAAG,CAAC,oBAAoB,CAAC,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC;IACpD,OAAO,OAAO,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC;AACxD,CAAC;AAED,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,iBAAiB,IAAI,CAAC,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,UAA0C,OAAO,CAAC,KAAK,EACvD,QAAwC,OAAO,CAAC,MAAM;IAEtD,IAAI,EAAyB,CAAC;IAC9B,MAAM,KAAK,GAAG,GAAc,EAAE;QAC5B,EAAE,KAAK,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1D,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,0EAA0E;IAC1E,wEAAwE;IACxE,4DAA4D;IAC5D,MAAM,WAAW,GAAG,KAAK,EAAK,IAAsB,EAAc,EAAE;QAClE,EAAE,EAAE,KAAK,EAAE,CAAC;QACZ,EAAE,GAAG,SAAS,CAAC;QACf,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAE9C,MAAM,IAAI,GAAgB;QACxB,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YACtB,MAAM,QAAQ,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,QAAQ,EAAE,EAAE;gBACtD,KAAK,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACrC,CAAC,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;QACzB,CAAC;QAED,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAClC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC;gBACvE,OAAO,iBAAiB,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YACtC,CAAC;YACD,OAAO,WAAW,CAAC,GAAG,EAAE,CACtB,OAAO,CAAC;gBACN,OAAO,EAAE,MAAM;gBACf,OAAO,EAAE,MAAM;gBACf,KAAK,EAAE;oBACL,+DAA+D;oBAC/D,6DAA6D;oBAC7D,gEAAgE;oBAChE,0DAA0D;oBAC1D,QAAQ,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE;oBACnC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;iBAC3C;aACF,CAAC,CACH,CAAC;QACJ,CAAC;QAED,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YAClB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QAED,MAAM,EAAE,GAAG,EAAE;YACX,EAAE,EAAE,KAAK,EAAE,CAAC;YACZ,EAAE,GAAG,SAAS,CAAC;QACjB,CAAC;KACF,CAAC;IAEF,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAE5B,OAAO;QACL,GAAG,IAAI;QACP,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAClB,WAAW,CAAC,KAAK,IAAI,EAAE;YACrB,IAAI,CAAC;gBACH,OAAO,MAAM,QAAQ,CAAC;oBACpB,OAAO,EAAE,CAAC,CAAC,MAAM;oBACjB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBAC3B,IAAI,EAAE,CAAC,CAAC,MAAM;wBACd,KAAK,EAAE,CAAC,CAAC,KAAK;wBACd,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,KAAK;qBAC5B,CAAC,CAAC;oBACH,KAAK,EAAE;wBACL,IAAI,EAAE;4BACJ,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;4BAC3C,SAAS,EAAE,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;4BACzC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;yBAC3C;wBACD,KAAK,EAAE;4BACL,2DAA2D;4BAC3D,mDAAmD;4BACnD,WAAW,EAAE,GAAG,EAAE,CAChB,MAAM,CAAC,+CAA+C,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;yBAC7E;qBACF;oBACD,8DAA8D;oBAC9D,iDAAiD;oBACjD,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;iBACtC,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,QAAQ,CAAC,CAAC,CAAC;oBAAE,OAAO,SAAS,CAAC;gBAClC,MAAM,CAAC,CAAC;YACV,CAAC;QACH,CAAC,CAAC;KACL,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAA4B,EAC5B,SAAsD;IAEtD,MAAM,SAAS,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;IACjC,MAAM,QAAQ,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IACtE,IAAI,OAAO,GAAG,EAAE,CAAC;IAEjB,MAAM,CAAC,GAA4C;QACjD,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE;YAChB,OAAO,IAAI,MAAM,CAAC;YAClB,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;YAC5B,OAAO,IAAI,MAAM,CAAC;YAClB,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC;YAC5B,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QAC9F,CAAC;QACD,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YAClB,OAAO,IAAI,KAAK,CAAC;QACnB,CAAC;QACD,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;QAChB,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO;KACvB,CAAC;IAEF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE;YACf,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC;YACpB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK;gBAAE,OAAO,IAAI,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;YACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjC,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;QACpE,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CAAC,QAAgB,EAAE,KAAa;IACxE,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAEtC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;QACrE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QAC3C,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK;YAAE,OAAO,SAAS,CAAC;QACzC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,MAAe;IACjE,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxC,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,MAAM,CAAC;IAC5B,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A identidade visual do CLI no terminal.
|
|
3
|
+
*
|
|
4
|
+
* Cor aqui é enfeite, nunca informação: todo texto continua legível sem
|
|
5
|
+
* nenhum código ANSI. É o que mantém a saída utilizável em log, em pipe e
|
|
6
|
+
* em terminal que não suporta cor — e é por isso que `pintar` devolve o
|
|
7
|
+
* texto cru quando a cor está desligada, em vez de um fallback diferente.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Respeita NO_COLOR (no-color.org) e FORCE_COLOR, nesta ordem.
|
|
11
|
+
*
|
|
12
|
+
* Sem TTY não há cor: escrever ANSI num pipe suja o arquivo de quem
|
|
13
|
+
* redirecionou a saída.
|
|
14
|
+
*/
|
|
15
|
+
export declare function temCor(env?: NodeJS.ProcessEnv, tty?: boolean): boolean;
|
|
16
|
+
type Estilo = "azul" | "azulClaro" | "cinza" | "negrito" | "branco";
|
|
17
|
+
export declare function pintar(texto: string, estilo: Estilo, cor?: boolean): string;
|
|
18
|
+
/**
|
|
19
|
+
* O bloco de abertura do `init`.
|
|
20
|
+
*
|
|
21
|
+
* O desenho é feito com meio-bloco (▀▄) para o logotipo caber em poucas
|
|
22
|
+
* linhas sem virar arte ASCII ilegível — a intenção é enquadrar o comando,
|
|
23
|
+
* não ocupar a tela inteira.
|
|
24
|
+
*/
|
|
25
|
+
export declare function hero(versao: string, cor?: boolean): string;
|
|
26
|
+
/** Linha de seção, para separar as etapas do wizard sem poluir. */
|
|
27
|
+
export declare function secao(titulo: string, cor?: boolean): string;
|
|
28
|
+
/** O fecho do init, quando deu certo. */
|
|
29
|
+
export declare function sucesso(linhas: readonly string[], cor?: boolean): string;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A identidade visual do CLI no terminal.
|
|
3
|
+
*
|
|
4
|
+
* Cor aqui é enfeite, nunca informação: todo texto continua legível sem
|
|
5
|
+
* nenhum código ANSI. É o que mantém a saída utilizável em log, em pipe e
|
|
6
|
+
* em terminal que não suporta cor — e é por isso que `pintar` devolve o
|
|
7
|
+
* texto cru quando a cor está desligada, em vez de um fallback diferente.
|
|
8
|
+
*/
|
|
9
|
+
const ESC = "[";
|
|
10
|
+
/**
|
|
11
|
+
* Respeita NO_COLOR (no-color.org) e FORCE_COLOR, nesta ordem.
|
|
12
|
+
*
|
|
13
|
+
* Sem TTY não há cor: escrever ANSI num pipe suja o arquivo de quem
|
|
14
|
+
* redirecionou a saída.
|
|
15
|
+
*/
|
|
16
|
+
export function temCor(env = process.env, tty = process.stdout.isTTY === true) {
|
|
17
|
+
if (env["NO_COLOR"] !== undefined && env["NO_COLOR"] !== "")
|
|
18
|
+
return false;
|
|
19
|
+
if (env["FORCE_COLOR"] !== undefined && env["FORCE_COLOR"] !== "0")
|
|
20
|
+
return true;
|
|
21
|
+
if (env["TERM"] === "dumb")
|
|
22
|
+
return false;
|
|
23
|
+
return tty;
|
|
24
|
+
}
|
|
25
|
+
const CODIGOS = {
|
|
26
|
+
// O azul do expxdev. 256 cores em vez de 16: o azul básico do terminal
|
|
27
|
+
// varia demais entre temas, e a marca precisa ser a mesma em todos.
|
|
28
|
+
azul: "38;5;33",
|
|
29
|
+
azulClaro: "38;5;75",
|
|
30
|
+
cinza: "38;5;245",
|
|
31
|
+
negrito: "1",
|
|
32
|
+
branco: "38;5;255",
|
|
33
|
+
};
|
|
34
|
+
export function pintar(texto, estilo, cor = temCor()) {
|
|
35
|
+
if (!cor)
|
|
36
|
+
return texto;
|
|
37
|
+
return `${ESC}${CODIGOS[estilo]}m${texto}${ESC}0m`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* O bloco de abertura do `init`.
|
|
41
|
+
*
|
|
42
|
+
* O desenho é feito com meio-bloco (▀▄) para o logotipo caber em poucas
|
|
43
|
+
* linhas sem virar arte ASCII ilegível — a intenção é enquadrar o comando,
|
|
44
|
+
* não ocupar a tela inteira.
|
|
45
|
+
*/
|
|
46
|
+
export function hero(versao, cor = temCor()) {
|
|
47
|
+
const a = (t) => pintar(t, "azul", cor);
|
|
48
|
+
const c = (t) => pintar(t, "azulClaro", cor);
|
|
49
|
+
const g = (t) => pintar(t, "cinza", cor);
|
|
50
|
+
const b = (t) => pintar(t, "negrito", cor);
|
|
51
|
+
return [
|
|
52
|
+
"",
|
|
53
|
+
` ${a("███████╗")}${c("██╗ ██╗")}${a("██████╗ ")}${c("██╗ ██╗")} ${g("dev")}`,
|
|
54
|
+
` ${a("██╔════╝")}${c("╚██╗██╔╝")}${a("██╔══██╗")}${c("╚██╗██╔╝")}`,
|
|
55
|
+
` ${a("█████╗ ")}${c(" ╚███╔╝ ")}${a("██████╔╝")}${c(" ╚███╔╝ ")}`,
|
|
56
|
+
` ${a("██╔══╝ ")}${c(" ██╔██╗ ")}${a("██╔═══╝ ")}${c(" ██╔██╗ ")}`,
|
|
57
|
+
` ${a("███████╗")}${c("██╔╝ ██╗")}${a("██║ ")}${c("██╔╝ ██╗")}`,
|
|
58
|
+
` ${a("╚══════╝")}${c("╚═╝ ╚═╝")}${a("╚═╝ ")}${c("╚═╝ ╚═╝")}`,
|
|
59
|
+
"",
|
|
60
|
+
` ${b("o metodo Expx no seu projeto")} ${g(`v${versao}`)}`,
|
|
61
|
+
"",
|
|
62
|
+
].join("\n");
|
|
63
|
+
}
|
|
64
|
+
/** Linha de seção, para separar as etapas do wizard sem poluir. */
|
|
65
|
+
export function secao(titulo, cor = temCor()) {
|
|
66
|
+
return `\n${pintar("▸", "azulClaro", cor)} ${pintar(titulo, "negrito", cor)}\n`;
|
|
67
|
+
}
|
|
68
|
+
/** O fecho do init, quando deu certo. */
|
|
69
|
+
export function sucesso(linhas, cor = temCor()) {
|
|
70
|
+
const marca = pintar("✓", "azulClaro", cor);
|
|
71
|
+
return `\n${marca} ${linhas.join(`\n `)}\n`;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=visual.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual.js","sourceRoot":"","sources":["../../src/cli/visual.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type OpcoesInitCli } from "./init-flags.js";
|
|
2
|
+
import { interpretarSimNao, type Perguntador } from "./perguntar.js";
|
|
3
|
+
/**
|
|
4
|
+
* As quatro perguntas do `init` interativo (especificação, promptcli1.md:51-68).
|
|
5
|
+
*
|
|
6
|
+
* O wizard não instala nada: ele só transforma "nenhuma flag" em uma seleção
|
|
7
|
+
* completa e devolve. Quem escreve em disco continua sendo `executarInit`, com
|
|
8
|
+
* exatamente o mesmo caminho que as flags percorrem — é o que garante que o
|
|
9
|
+
* modo interativo e o modo `--skills` não divirjam em comportamento.
|
|
10
|
+
*
|
|
11
|
+
* Toda pergunta respeita o que já veio por flag: quem passou `--harness` não é
|
|
12
|
+
* perguntado de novo. Isso permite responder metade por flag e metade na mão.
|
|
13
|
+
*
|
|
14
|
+
* Há dois modos de responder. O padrão é navegar e marcar com as setas; onde
|
|
15
|
+
* isso não funciona — CI, pipe, `TERM=dumb` — o mesmo wizard cai para a
|
|
16
|
+
* escolha por número, que não exige nada do terminal. Os dois produzem a
|
|
17
|
+
* mesma seleção, e é o `Perguntador` que decide qual está disponível.
|
|
18
|
+
*/
|
|
19
|
+
export type ResultadoWizard = {
|
|
20
|
+
ok: true;
|
|
21
|
+
opcoes: OpcoesInitCli;
|
|
22
|
+
} | {
|
|
23
|
+
ok: false;
|
|
24
|
+
erro: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function executarWizard(p: Perguntador, parciais: OpcoesInitCli, raiz: string): Promise<ResultadoWizard>;
|
|
27
|
+
export { interpretarSimNao };
|