expxdev 0.3.0 → 0.4.1
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.js +14 -5
- package/dist/cli/expx.js.map +1 -1
- package/dist/cli/init.js +9 -3
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/perguntar.d.ts +47 -9
- package/dist/cli/perguntar.js +109 -6
- package/dist/cli/perguntar.js.map +1 -1
- 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 +7 -1
- package/dist/cli/wizard.js +113 -47
- package/dist/cli/wizard.js.map +1 -1
- package/dist/watch/fontes/cauda.d.ts +14 -0
- package/dist/watch/fontes/cauda.js +49 -0
- package/dist/watch/fontes/cauda.js.map +1 -0
- package/dist/watch/fontes/estado-schema.d.ts +78 -0
- package/dist/watch/fontes/estado-schema.js +72 -0
- package/dist/watch/fontes/estado-schema.js.map +1 -0
- package/dist/watch/fontes/estado.d.ts +18 -0
- package/dist/watch/fontes/estado.js +38 -0
- package/dist/watch/fontes/estado.js.map +1 -0
- package/dist/watch/fontes/rastro.d.ts +17 -0
- package/dist/watch/fontes/rastro.js +43 -0
- package/dist/watch/fontes/rastro.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/wizard.js
CHANGED
|
@@ -3,53 +3,104 @@ import { avaliarSelecao } from "./selecao.js";
|
|
|
3
3
|
import { detectarProjeto } from "./projeto.js";
|
|
4
4
|
import { HARNESS_VALIDOS } from "./init-flags.js";
|
|
5
5
|
import { interpretarEscolhaMultipla, interpretarSimNao } from "./perguntar.js";
|
|
6
|
+
import { pintar, secao, temCor } from "./visual.js";
|
|
6
7
|
const TENTATIVAS = 3;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const marca = s.camada ? " (camada)" : "";
|
|
11
|
-
p.escrever(` ${String(i + 1)}. ${s.nome}${marca} — ${s.papel}\n`);
|
|
12
|
-
});
|
|
13
|
-
p.escrever("\nResponda com os numeros separados por virgula (ex.: 1,5).\n");
|
|
8
|
+
/** Cancelar no menu (Esc/Ctrl+C) vira erro; aqui vira "cancelado", não travamento. */
|
|
9
|
+
function foiCancelado(e) {
|
|
10
|
+
return e instanceof Error && (e.name === "ExitPromptError" || e.name === "AbortPromptError");
|
|
14
11
|
}
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
function rotuloDaSkill(nome, papel, camada, cor) {
|
|
13
|
+
const marca = camada ? ` ${pintar("(camada)", "cinza", cor)}` : "";
|
|
14
|
+
return `${pintar(nome, "branco", cor)}${marca} ${pintar(papel, "cinza", cor)}`;
|
|
15
|
+
}
|
|
16
|
+
async function marcarSkills(p) {
|
|
17
|
+
const cor = temCor();
|
|
17
18
|
for (let tentativa = 0; tentativa < TENTATIVAS; tentativa++) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
let selecao;
|
|
20
|
+
if (p.marcar !== undefined) {
|
|
21
|
+
const escolhido = await p.marcar({
|
|
22
|
+
titulo: "Quais skills instalar neste projeto?",
|
|
23
|
+
itens: CATALOGO.map((s) => ({
|
|
24
|
+
valor: s.nome,
|
|
25
|
+
rotulo: rotuloDaSkill(s.nome, s.papel, s.camada, cor),
|
|
26
|
+
})),
|
|
27
|
+
});
|
|
28
|
+
if (escolhido === undefined)
|
|
29
|
+
return undefined;
|
|
30
|
+
selecao = escolhido;
|
|
23
31
|
}
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
else {
|
|
33
|
+
const lido = await escolherPorNumero(p);
|
|
34
|
+
if (lido === undefined)
|
|
35
|
+
continue;
|
|
36
|
+
selecao = lido;
|
|
37
|
+
}
|
|
38
|
+
if (selecao.length === 0) {
|
|
39
|
+
p.escrever(`${pintar("nenhuma skill marcada: marque ao menos uma", "cinza", cor)}\n`);
|
|
26
40
|
continue;
|
|
27
41
|
}
|
|
28
|
-
const selecao = indices.map((i) => CATALOGO[i]?.nome ?? "");
|
|
29
42
|
const aval = avaliarSelecao(selecao);
|
|
30
43
|
// Aviso nunca impede: a combinação incomum pode ser exatamente a pedida.
|
|
31
44
|
// O CLI explica a consequência e deixa a pessoa confirmar (selecao.ts).
|
|
32
45
|
if (aval.precisaConfirmar) {
|
|
33
46
|
for (const a of aval.avisos)
|
|
34
|
-
p.escrever(`\
|
|
35
|
-
|
|
36
|
-
if (!segue) {
|
|
47
|
+
p.escrever(`\n${pintar("aviso:", "negrito", cor)} ${a}\n`);
|
|
48
|
+
if (!(await p.confirmar("seguir assim mesmo?", false))) {
|
|
37
49
|
p.escrever("\nescolha de novo:\n");
|
|
38
50
|
continue;
|
|
39
51
|
}
|
|
40
52
|
}
|
|
41
53
|
for (const i of aval.integracoes) {
|
|
42
|
-
p.escrever(
|
|
54
|
+
p.escrever(`${pintar("integracao:", "azulClaro", cor)} ${i} se conecta com as skills escolhidas\n`);
|
|
43
55
|
}
|
|
44
56
|
return selecao;
|
|
45
57
|
}
|
|
46
58
|
return undefined;
|
|
47
59
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
p.escrever("
|
|
52
|
-
|
|
60
|
+
/** O caminho sem navegação: a lista numerada e uma linha de resposta. */
|
|
61
|
+
async function escolherPorNumero(p) {
|
|
62
|
+
const cor = temCor();
|
|
63
|
+
p.escrever(secao("Quais skills instalar neste projeto?", cor));
|
|
64
|
+
CATALOGO.forEach((s, i) => {
|
|
65
|
+
p.escrever(` ${String(i + 1)}. ${rotuloDaSkill(s.nome, s.papel, s.camada, cor)}\n`);
|
|
66
|
+
});
|
|
67
|
+
p.escrever(`\n${pintar("numeros separados por virgula (ex.: 1,5)", "cinza", cor)}\n`);
|
|
68
|
+
const indices = interpretarEscolhaMultipla(await p.linha("skills: "), CATALOGO.length);
|
|
69
|
+
if (indices === undefined) {
|
|
70
|
+
p.escrever(`numero invalido: responda entre 1 e ${String(CATALOGO.length)}\n`);
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
return indices.map((i) => CATALOGO[i]?.nome ?? "");
|
|
74
|
+
}
|
|
75
|
+
async function marcarHarness(p) {
|
|
76
|
+
const cor = temCor();
|
|
77
|
+
const descricao = {
|
|
78
|
+
claude: "Claude Code",
|
|
79
|
+
opencode: "OpenCode",
|
|
80
|
+
};
|
|
81
|
+
if (p.marcar !== undefined) {
|
|
82
|
+
for (let tentativa = 0; tentativa < TENTATIVAS; tentativa++) {
|
|
83
|
+
const escolhido = await p.marcar({
|
|
84
|
+
titulo: "Qual harness configurar?",
|
|
85
|
+
itens: HARNESS_VALIDOS.map((h) => ({
|
|
86
|
+
valor: h,
|
|
87
|
+
rotulo: `${pintar(h, "branco", cor)} ${pintar(descricao[h], "cinza", cor)}`,
|
|
88
|
+
marcado: h === "claude",
|
|
89
|
+
})),
|
|
90
|
+
});
|
|
91
|
+
if (escolhido === undefined)
|
|
92
|
+
return undefined;
|
|
93
|
+
if (escolhido.length > 0)
|
|
94
|
+
return escolhido;
|
|
95
|
+
p.escrever(`${pintar("marque ao menos um harness", "cinza", cor)}\n`);
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
p.escrever(secao("Qual harness configurar?", cor));
|
|
100
|
+
HARNESS_VALIDOS.forEach((h, i) => {
|
|
101
|
+
p.escrever(` ${String(i + 1)}. ${h} — ${descricao[h]}\n`);
|
|
102
|
+
});
|
|
103
|
+
p.escrever(`\n${pintar("os dois: 1,2. vazio usa claude.", "cinza", cor)}\n`);
|
|
53
104
|
for (let tentativa = 0; tentativa < TENTATIVAS; tentativa++) {
|
|
54
105
|
const resposta = await p.linha("harness [1]: ");
|
|
55
106
|
if (resposta.trim() === "")
|
|
@@ -72,30 +123,45 @@ async function escolherHarness(p) {
|
|
|
72
123
|
async function confirmarReconfiguracao(p, raiz) {
|
|
73
124
|
if (!detectarProjeto(raiz).existe)
|
|
74
125
|
return true;
|
|
75
|
-
|
|
76
|
-
p.escrever("
|
|
77
|
-
|
|
126
|
+
const cor = temCor();
|
|
127
|
+
p.escrever(`\n${pintar("este projeto ja tem um .expx/ instalado", "negrito", cor)}\n`);
|
|
128
|
+
p.escrever(`${pintar("seguir remonta a instalacao a partir da nova selecao", "cinza", cor)}\n`);
|
|
129
|
+
return p.confirmar("reconfigurar?", false);
|
|
78
130
|
}
|
|
79
131
|
export async function executarWizard(p, parciais, raiz) {
|
|
80
|
-
|
|
81
|
-
|
|
132
|
+
const cor = temCor();
|
|
133
|
+
try {
|
|
134
|
+
if (!(await confirmarReconfiguracao(p, raiz))) {
|
|
135
|
+
return { ok: false, erro: "reconfiguracao cancelada: nada foi alterado" };
|
|
136
|
+
}
|
|
137
|
+
const skills = parciais.skills.length > 0 ? parciais.skills : await marcarSkills(p);
|
|
138
|
+
if (skills === undefined)
|
|
139
|
+
return { ok: false, erro: "cancelado: nada foi alterado" };
|
|
140
|
+
const harness = parciais.harness.length > 0 ? parciais.harness : await marcarHarness(p);
|
|
141
|
+
if (harness === undefined)
|
|
142
|
+
return { ok: false, erro: "cancelado: nada foi alterado" };
|
|
143
|
+
const painel = parciais.painel
|
|
144
|
+
? true
|
|
145
|
+
: await p.confirmar("instalar o painel como devDependency?", false);
|
|
146
|
+
p.escrever(secao("Resumo", cor));
|
|
147
|
+
p.escrever(` skills ${pintar(skills.join(", "), "branco", cor)}\n`);
|
|
148
|
+
p.escrever(` harness ${pintar(harness.join(", "), "branco", cor)}\n`);
|
|
149
|
+
if (painel)
|
|
150
|
+
p.escrever(` painel ${pintar("sim", "branco", cor)}\n`);
|
|
151
|
+
p.escrever("\n");
|
|
152
|
+
if (!(await p.confirmar("confirmar?", true))) {
|
|
153
|
+
return { ok: false, erro: "cancelado: nada foi alterado" };
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
ok: true,
|
|
157
|
+
opcoes: { skills: [...skills], harness: [...harness], painel, sim: true, simular: parciais.simular },
|
|
158
|
+
};
|
|
82
159
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (harness === undefined)
|
|
88
|
-
return { ok: false, erro: "harness invalido apos varias tentativas" };
|
|
89
|
-
const painel = parciais.painel
|
|
90
|
-
? true
|
|
91
|
-
: interpretarSimNao(await p.linha("\nInstalar o painel como devDependency? [s/N] "), false);
|
|
92
|
-
p.escrever(`\nvai instalar: ${skills.join(", ")}\n`);
|
|
93
|
-
p.escrever(`harness: ${harness.join(", ")}\n`);
|
|
94
|
-
if (painel)
|
|
95
|
-
p.escrever("painel: sim\n");
|
|
96
|
-
if (!interpretarSimNao(await p.linha("\nconfirmar? [S/n] "), true)) {
|
|
97
|
-
return { ok: false, erro: "cancelado: nada foi alterado" };
|
|
160
|
+
catch (e) {
|
|
161
|
+
if (foiCancelado(e))
|
|
162
|
+
return { ok: false, erro: "cancelado: nada foi alterado" };
|
|
163
|
+
throw e;
|
|
98
164
|
}
|
|
99
|
-
return { ok: true, opcoes: { skills: [...skills], harness: [...harness], painel, sim: true, simular: parciais.simular } };
|
|
100
165
|
}
|
|
166
|
+
export { interpretarSimNao };
|
|
101
167
|
//# sourceMappingURL=wizard.js.map
|
package/dist/cli/wizard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../src/cli/wizard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAoC,MAAM,iBAAiB,CAAC;AACpF,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,EAAoB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../src/cli/wizard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lê apenas o fim de um arquivo de texto, em linhas completas.
|
|
3
|
+
*
|
|
4
|
+
* O rastro só rotaciona em 5 MB (contrato `expx-eventos`), e o watch relê a
|
|
5
|
+
* cada evento novo. Ler o arquivo inteiro todas as vezes é a "chamada externa
|
|
6
|
+
* cara" que a especificação proíbe — daí a decisão D-09 de ler só a cauda.
|
|
7
|
+
*
|
|
8
|
+
* O preço de ler pelo fim é cortar a primeira linha ao meio. Este módulo
|
|
9
|
+
* DESCARTA esse fragmento: quem consome recebe só linhas íntegras, e uma linha
|
|
10
|
+
* perdida no começo da janela é irrelevante para "as últimas N linhas".
|
|
11
|
+
*/
|
|
12
|
+
/** Teto de bytes lidos por arquivo. */
|
|
13
|
+
export declare const LIMITE_CAUDA: number;
|
|
14
|
+
export declare function lerCauda(caminho: string, limite?: number): string[];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { closeSync, openSync, readSync, statSync } from "node:fs";
|
|
2
|
+
/**
|
|
3
|
+
* Lê apenas o fim de um arquivo de texto, em linhas completas.
|
|
4
|
+
*
|
|
5
|
+
* O rastro só rotaciona em 5 MB (contrato `expx-eventos`), e o watch relê a
|
|
6
|
+
* cada evento novo. Ler o arquivo inteiro todas as vezes é a "chamada externa
|
|
7
|
+
* cara" que a especificação proíbe — daí a decisão D-09 de ler só a cauda.
|
|
8
|
+
*
|
|
9
|
+
* O preço de ler pelo fim é cortar a primeira linha ao meio. Este módulo
|
|
10
|
+
* DESCARTA esse fragmento: quem consome recebe só linhas íntegras, e uma linha
|
|
11
|
+
* perdida no começo da janela é irrelevante para "as últimas N linhas".
|
|
12
|
+
*/
|
|
13
|
+
/** Teto de bytes lidos por arquivo. */
|
|
14
|
+
export const LIMITE_CAUDA = 64 * 1024;
|
|
15
|
+
export function lerCauda(caminho, limite = LIMITE_CAUDA) {
|
|
16
|
+
let fd;
|
|
17
|
+
try {
|
|
18
|
+
const tamanho = statSync(caminho).size;
|
|
19
|
+
if (tamanho === 0)
|
|
20
|
+
return [];
|
|
21
|
+
const inicio = Math.max(0, tamanho - limite);
|
|
22
|
+
const bytes = tamanho - inicio;
|
|
23
|
+
fd = openSync(caminho, "r");
|
|
24
|
+
const buf = Buffer.allocUnsafe(bytes);
|
|
25
|
+
readSync(fd, buf, 0, bytes, inicio);
|
|
26
|
+
const texto = buf.toString("utf8");
|
|
27
|
+
const linhas = texto.split("\n");
|
|
28
|
+
// Cortamos no meio do arquivo? Então a primeira linha é um fragmento do
|
|
29
|
+
// que veio antes da janela, e não um registro. Fora.
|
|
30
|
+
if (inicio > 0)
|
|
31
|
+
linhas.shift();
|
|
32
|
+
return linhas.filter((l) => l.trim() !== "");
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// arquivo ausente, sem permissão, sumiu entre o stat e o open: sem rastro
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
if (fd !== undefined) {
|
|
40
|
+
try {
|
|
41
|
+
closeSync(fd);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// fechar não pode derrubar quem só queria ler
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=cauda.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cauda.js","sourceRoot":"","sources":["../../../src/watch/fontes/cauda.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAElE;;;;;;;;;;GAUG;AAEH,uCAAuC;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,GAAG,IAAI,CAAC;AAEtC,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,SAAiB,YAAY;IACrE,IAAI,EAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC;QACvC,IAAI,OAAO,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAE7B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;QAE/B,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACtC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAEpC,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEjC,wEAAwE;QACxE,qDAAqD;QACrD,IAAI,MAAM,GAAG,CAAC;YAAE,MAAM,CAAC,KAAK,EAAE,CAAC;QAE/B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,OAAO,EAAE,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,SAAS,CAAC,EAAE,CAAC,CAAC;YAChB,CAAC;YAAC,MAAM,CAAC;gBACP,8CAA8C;YAChD,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Contrato `expx-estado` v1 — o arquivo que a barra de status lê.
|
|
4
|
+
*
|
|
5
|
+
* Primeiro leitor deste contrato no repositório: a busca por
|
|
6
|
+
* `estado.json|expx_estado` em `src/`, `ui/` e `nucleo/` não devolvia nada.
|
|
7
|
+
*
|
|
8
|
+
* Os enums vêm do `expx-schema` de propósito. A regra 7 do contrato manda que
|
|
9
|
+
* sejam os MESMOS ("minúsculo, sem acento; `e3`, não `E3`"), e redeclará-los
|
|
10
|
+
* aqui criaria duas listas que divergem com o tempo — foi exatamente assim que
|
|
11
|
+
* as listas de chaves do rastro divergiram entre duas skills
|
|
12
|
+
* (ver `src/parser/esquema/evento.ts`).
|
|
13
|
+
*/
|
|
14
|
+
/** A versão que este leitor entende. Diferente disso é degradado (D-12). */
|
|
15
|
+
export declare const VERSAO_ESTADO = 1;
|
|
16
|
+
/**
|
|
17
|
+
* As quinze chaves do contrato, na ordem do documento.
|
|
18
|
+
*
|
|
19
|
+
* Exportada porque o teste percorre a lista removendo uma por vez: sem ela, a
|
|
20
|
+
* verificação da R6 seria quinze blocos copiados.
|
|
21
|
+
*/
|
|
22
|
+
export declare const CHAVES_ESTADO: readonly ["expx_estado", "atualizado_em", "trabalho", "ferramenta", "titulo_curto", "fase", "task", "tasks_concluidas", "tasks_total", "raio", "orcamento_arquivos", "orcamento_linhas", "branch", "pr_estado", "bloqueios"];
|
|
23
|
+
/** Faixa de raio do modo legado. `null` fora dele (regra 2 do contrato). */
|
|
24
|
+
export declare const Raio: z.ZodEnum<{
|
|
25
|
+
baixo: "baixo";
|
|
26
|
+
medio: "medio";
|
|
27
|
+
alto: "alto";
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Nenhum campo é `.optional()`: a regra 2 do contrato ("chave nunca omitida")
|
|
31
|
+
* é o que permite ao leitor distinguir "não se aplica" de "esqueceram de
|
|
32
|
+
* escrever". Ausente é `null`, e `null` é um valor presente.
|
|
33
|
+
*
|
|
34
|
+
* Sem `.passthrough()`: ao contrário do rastro, que declara chaves extras por
|
|
35
|
+
* skill, o `expx-estado` fixa quinze chaves e um limite de 1 KB. Chave a mais
|
|
36
|
+
* aqui é sinal de escritor fora do contrato, não de extensão legítima.
|
|
37
|
+
*/
|
|
38
|
+
export declare const EstadoExpx: z.ZodObject<{
|
|
39
|
+
expx_estado: z.ZodLiteral<1>;
|
|
40
|
+
atualizado_em: z.ZodString;
|
|
41
|
+
trabalho: z.ZodNullable<z.ZodString>;
|
|
42
|
+
ferramenta: z.ZodNullable<z.ZodEnum<{
|
|
43
|
+
sprintx: "sprintx";
|
|
44
|
+
runx: "runx";
|
|
45
|
+
mergex: "mergex";
|
|
46
|
+
legadox: "legadox";
|
|
47
|
+
stackx: "stackx";
|
|
48
|
+
memox: "memox";
|
|
49
|
+
}>>;
|
|
50
|
+
titulo_curto: z.ZodNullable<z.ZodString>;
|
|
51
|
+
fase: z.ZodNullable<z.ZodEnum<{
|
|
52
|
+
f1: "f1";
|
|
53
|
+
f2: "f2";
|
|
54
|
+
f3: "f3";
|
|
55
|
+
f4: "f4";
|
|
56
|
+
f5: "f5";
|
|
57
|
+
f6: "f6";
|
|
58
|
+
e1: "e1";
|
|
59
|
+
e2: "e2";
|
|
60
|
+
e3: "e3";
|
|
61
|
+
e4: "e4";
|
|
62
|
+
e5: "e5";
|
|
63
|
+
}>>;
|
|
64
|
+
task: z.ZodNullable<z.ZodString>;
|
|
65
|
+
tasks_concluidas: z.ZodNumber;
|
|
66
|
+
tasks_total: z.ZodNumber;
|
|
67
|
+
raio: z.ZodNullable<z.ZodEnum<{
|
|
68
|
+
baixo: "baixo";
|
|
69
|
+
medio: "medio";
|
|
70
|
+
alto: "alto";
|
|
71
|
+
}>>;
|
|
72
|
+
orcamento_arquivos: z.ZodNullable<z.ZodString>;
|
|
73
|
+
orcamento_linhas: z.ZodNullable<z.ZodString>;
|
|
74
|
+
branch: z.ZodNullable<z.ZodString>;
|
|
75
|
+
pr_estado: z.ZodNullable<z.ZodString>;
|
|
76
|
+
bloqueios: z.ZodNumber;
|
|
77
|
+
}, z.core.$strip>;
|
|
78
|
+
export type EstadoExpx = z.infer<typeof EstadoExpx>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Estagio, Ferramenta } from "../../parser/esquema/enums.js";
|
|
3
|
+
/**
|
|
4
|
+
* Contrato `expx-estado` v1 — o arquivo que a barra de status lê.
|
|
5
|
+
*
|
|
6
|
+
* Primeiro leitor deste contrato no repositório: a busca por
|
|
7
|
+
* `estado.json|expx_estado` em `src/`, `ui/` e `nucleo/` não devolvia nada.
|
|
8
|
+
*
|
|
9
|
+
* Os enums vêm do `expx-schema` de propósito. A regra 7 do contrato manda que
|
|
10
|
+
* sejam os MESMOS ("minúsculo, sem acento; `e3`, não `E3`"), e redeclará-los
|
|
11
|
+
* aqui criaria duas listas que divergem com o tempo — foi exatamente assim que
|
|
12
|
+
* as listas de chaves do rastro divergiram entre duas skills
|
|
13
|
+
* (ver `src/parser/esquema/evento.ts`).
|
|
14
|
+
*/
|
|
15
|
+
/** A versão que este leitor entende. Diferente disso é degradado (D-12). */
|
|
16
|
+
export const VERSAO_ESTADO = 1;
|
|
17
|
+
/**
|
|
18
|
+
* As quinze chaves do contrato, na ordem do documento.
|
|
19
|
+
*
|
|
20
|
+
* Exportada porque o teste percorre a lista removendo uma por vez: sem ela, a
|
|
21
|
+
* verificação da R6 seria quinze blocos copiados.
|
|
22
|
+
*/
|
|
23
|
+
export const CHAVES_ESTADO = [
|
|
24
|
+
"expx_estado",
|
|
25
|
+
"atualizado_em",
|
|
26
|
+
"trabalho",
|
|
27
|
+
"ferramenta",
|
|
28
|
+
"titulo_curto",
|
|
29
|
+
"fase",
|
|
30
|
+
"task",
|
|
31
|
+
"tasks_concluidas",
|
|
32
|
+
"tasks_total",
|
|
33
|
+
"raio",
|
|
34
|
+
"orcamento_arquivos",
|
|
35
|
+
"orcamento_linhas",
|
|
36
|
+
"branch",
|
|
37
|
+
"pr_estado",
|
|
38
|
+
"bloqueios",
|
|
39
|
+
];
|
|
40
|
+
/** Faixa de raio do modo legado. `null` fora dele (regra 2 do contrato). */
|
|
41
|
+
export const Raio = z.enum(["baixo", "medio", "alto"]);
|
|
42
|
+
/** Timestamp do contrato: ISO-8601 em UTC, com `Z` (R4). */
|
|
43
|
+
const TimestampUtc = z
|
|
44
|
+
.string()
|
|
45
|
+
.regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/, "atualizado_em deve ser AAAA-MM-DDTHH:MM:SSZ");
|
|
46
|
+
/**
|
|
47
|
+
* Nenhum campo é `.optional()`: a regra 2 do contrato ("chave nunca omitida")
|
|
48
|
+
* é o que permite ao leitor distinguir "não se aplica" de "esqueceram de
|
|
49
|
+
* escrever". Ausente é `null`, e `null` é um valor presente.
|
|
50
|
+
*
|
|
51
|
+
* Sem `.passthrough()`: ao contrário do rastro, que declara chaves extras por
|
|
52
|
+
* skill, o `expx-estado` fixa quinze chaves e um limite de 1 KB. Chave a mais
|
|
53
|
+
* aqui é sinal de escritor fora do contrato, não de extensão legítima.
|
|
54
|
+
*/
|
|
55
|
+
export const EstadoExpx = z.object({
|
|
56
|
+
expx_estado: z.literal(VERSAO_ESTADO),
|
|
57
|
+
atualizado_em: TimestampUtc,
|
|
58
|
+
trabalho: z.string().min(1).nullable(),
|
|
59
|
+
ferramenta: Ferramenta.nullable(),
|
|
60
|
+
titulo_curto: z.string().nullable(),
|
|
61
|
+
fase: Estagio.nullable(),
|
|
62
|
+
task: z.string().nullable(),
|
|
63
|
+
tasks_concluidas: z.number().int().min(0),
|
|
64
|
+
tasks_total: z.number().int().min(0),
|
|
65
|
+
raio: Raio.nullable(),
|
|
66
|
+
orcamento_arquivos: z.string().nullable(),
|
|
67
|
+
orcamento_linhas: z.string().nullable(),
|
|
68
|
+
branch: z.string().nullable(),
|
|
69
|
+
pr_estado: z.string().nullable(),
|
|
70
|
+
bloqueios: z.number().int().min(0),
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=estado-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estado-schema.js","sourceRoot":"","sources":["../../../src/watch/fontes/estado-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEpE;;;;;;;;;;;GAWG;AAEH,4EAA4E;AAC5E,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAE/B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,aAAa;IACb,eAAe;IACf,UAAU;IACV,YAAY;IACZ,cAAc;IACd,MAAM;IACN,MAAM;IACN,kBAAkB;IAClB,aAAa;IACb,MAAM;IACN,oBAAoB;IACpB,kBAAkB;IAClB,QAAQ;IACR,WAAW;IACX,WAAW;CACH,CAAC;AAEX,4EAA4E;AAC5E,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvD,4DAA4D;AAC5D,MAAM,YAAY,GAAG,CAAC;KACnB,MAAM,EAAE;KACR,KAAK,CACJ,wCAAwC,EACxC,6CAA6C,CAC9C,CAAC;AAEJ;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IACrC,aAAa,EAAE,YAAY;IAC3B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACtC,UAAU,EAAE,UAAU,CAAC,QAAQ,EAAE;IACjC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE;IACxB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE;IACrB,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACzC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACvC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACnC,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { EstadoExpx } from "./estado-schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* Lê `.expx/estado.json` a partir da raiz do projeto.
|
|
4
|
+
*
|
|
5
|
+
* Falha SEMPRE para `null`, nunca lança. A regra 1 do contrato `expx-estado`
|
|
6
|
+
* declara o arquivo "derivado e descartável; apagá-lo não pode quebrar nada" —
|
|
7
|
+
* e o watch inteiro depende disso: a tolerância a falha "estado.json inválido
|
|
8
|
+
* cai para leitura direta do plano" é justamente este `null`.
|
|
9
|
+
*
|
|
10
|
+
* A leitura é de uma vez só porque o contrato exige escrita atômica (regra 3:
|
|
11
|
+
* temporário + rename). Não existe janela de leitura parcial: ou o arquivo
|
|
12
|
+
* antigo inteiro, ou o novo inteiro.
|
|
13
|
+
*
|
|
14
|
+
* Versão diferente de 1 é `null` de propósito (decisão D-12): o `EstadoExpx`
|
|
15
|
+
* declara `expx_estado: z.literal(1)`, então um arquivo de versão futura
|
|
16
|
+
* reprova no parse como qualquer outro defeito, e quem chama vai para o plano.
|
|
17
|
+
*/
|
|
18
|
+
export declare function lerEstadoExpx(raizProjeto: string): EstadoExpx | null;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { EstadoExpx } from "./estado-schema.js";
|
|
4
|
+
/**
|
|
5
|
+
* Lê `.expx/estado.json` a partir da raiz do projeto.
|
|
6
|
+
*
|
|
7
|
+
* Falha SEMPRE para `null`, nunca lança. A regra 1 do contrato `expx-estado`
|
|
8
|
+
* declara o arquivo "derivado e descartável; apagá-lo não pode quebrar nada" —
|
|
9
|
+
* e o watch inteiro depende disso: a tolerância a falha "estado.json inválido
|
|
10
|
+
* cai para leitura direta do plano" é justamente este `null`.
|
|
11
|
+
*
|
|
12
|
+
* A leitura é de uma vez só porque o contrato exige escrita atômica (regra 3:
|
|
13
|
+
* temporário + rename). Não existe janela de leitura parcial: ou o arquivo
|
|
14
|
+
* antigo inteiro, ou o novo inteiro.
|
|
15
|
+
*
|
|
16
|
+
* Versão diferente de 1 é `null` de propósito (decisão D-12): o `EstadoExpx`
|
|
17
|
+
* declara `expx_estado: z.literal(1)`, então um arquivo de versão futura
|
|
18
|
+
* reprova no parse como qualquer outro defeito, e quem chama vai para o plano.
|
|
19
|
+
*/
|
|
20
|
+
export function lerEstadoExpx(raizProjeto) {
|
|
21
|
+
let bruto;
|
|
22
|
+
try {
|
|
23
|
+
bruto = readFileSync(join(raizProjeto, ".expx", "estado.json"), "utf8");
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null; // ausente, sem permissão, é um diretório: tudo é "não há estado"
|
|
27
|
+
}
|
|
28
|
+
let dados;
|
|
29
|
+
try {
|
|
30
|
+
dados = JSON.parse(bruto);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const r = EstadoExpx.safeParse(dados);
|
|
36
|
+
return r.success ? r.data : null;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=estado.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estado.js","sourceRoot":"","sources":["../../../src/watch/fontes/estado.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,IAAI,KAAa,CAAC;IAClB,IAAI,CAAC;QACH,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,iEAAiE;IAChF,CAAC;IAED,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACtC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { LinhaEvento } from "../../parser/esquema/evento.js";
|
|
2
|
+
/**
|
|
3
|
+
* Lê as últimas linhas do rastro de um trabalho, da mais recente para a mais
|
|
4
|
+
* antiga.
|
|
5
|
+
*
|
|
6
|
+
* O que o repositório já tinha era `validarRastro`, que conta defeitos e não
|
|
7
|
+
* devolve evento nenhum. O schema `LinhaEvento` e os enums, esses sim, são
|
|
8
|
+
* reaproveitados inteiros: são a fonte única do vocabulário do contrato.
|
|
9
|
+
*
|
|
10
|
+
* Rotação: acima de 5 MB o arquivo corrente vira `<id>.1.jsonl` e um novo
|
|
11
|
+
* começa (contrato `expx-eventos`), e "o painel lê os dois". O `.1` é o mais
|
|
12
|
+
* ANTIGO — inverter isso mostraria o rastro fora de ordem logo após uma
|
|
13
|
+
* rotação, que é justamente quando ninguém está olhando com atenção.
|
|
14
|
+
*/
|
|
15
|
+
/** Quantas linhas o watch exibe por padrão (decisão D-09). */
|
|
16
|
+
export declare const LINHAS_PADRAO = 10;
|
|
17
|
+
export declare function lerRastro(raizProjeto: string, trabalhoId: string, limite?: number): LinhaEvento[];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { LinhaEvento } from "../../parser/esquema/evento.js";
|
|
3
|
+
import { lerCauda } from "./cauda.js";
|
|
4
|
+
/**
|
|
5
|
+
* Lê as últimas linhas do rastro de um trabalho, da mais recente para a mais
|
|
6
|
+
* antiga.
|
|
7
|
+
*
|
|
8
|
+
* O que o repositório já tinha era `validarRastro`, que conta defeitos e não
|
|
9
|
+
* devolve evento nenhum. O schema `LinhaEvento` e os enums, esses sim, são
|
|
10
|
+
* reaproveitados inteiros: são a fonte única do vocabulário do contrato.
|
|
11
|
+
*
|
|
12
|
+
* Rotação: acima de 5 MB o arquivo corrente vira `<id>.1.jsonl` e um novo
|
|
13
|
+
* começa (contrato `expx-eventos`), e "o painel lê os dois". O `.1` é o mais
|
|
14
|
+
* ANTIGO — inverter isso mostraria o rastro fora de ordem logo após uma
|
|
15
|
+
* rotação, que é justamente quando ninguém está olhando com atenção.
|
|
16
|
+
*/
|
|
17
|
+
/** Quantas linhas o watch exibe por padrão (decisão D-09). */
|
|
18
|
+
export const LINHAS_PADRAO = 10;
|
|
19
|
+
export function lerRastro(raizProjeto, trabalhoId, limite = LINHAS_PADRAO) {
|
|
20
|
+
const dir = join(raizProjeto, "docs", "eventos");
|
|
21
|
+
// corrente primeiro, rotacionado depois: os dois já vêm em ordem
|
|
22
|
+
// cronológica crescente dentro de cada arquivo.
|
|
23
|
+
const cronologicas = [
|
|
24
|
+
...lerCauda(join(dir, `${trabalhoId}.1.jsonl`)),
|
|
25
|
+
...lerCauda(join(dir, `${trabalhoId}.jsonl`)),
|
|
26
|
+
];
|
|
27
|
+
const validas = [];
|
|
28
|
+
for (const bruta of cronologicas) {
|
|
29
|
+
let obj;
|
|
30
|
+
try {
|
|
31
|
+
obj = JSON.parse(bruta);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
continue; // linha malformada não derruba o resto do rastro
|
|
35
|
+
}
|
|
36
|
+
const r = LinhaEvento.safeParse(obj);
|
|
37
|
+
if (r.success)
|
|
38
|
+
validas.push(r.data);
|
|
39
|
+
}
|
|
40
|
+
// as N mais recentes, já invertidas para exibição
|
|
41
|
+
return validas.slice(-limite).reverse();
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=rastro.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rastro.js","sourceRoot":"","sources":["../../../src/watch/fontes/rastro.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC;;;;;;;;;;;;GAYG;AAEH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAEhC,MAAM,UAAU,SAAS,CACvB,WAAmB,EACnB,UAAkB,EAClB,SAAiB,aAAa;IAE9B,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;IAEjD,iEAAiE;IACjE,gDAAgD;IAChD,MAAM,YAAY,GAAG;QACnB,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,UAAU,CAAC,CAAC;QAC/C,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,QAAQ,CAAC,CAAC;KAC9C,CAAC;IAEF,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;QACjC,IAAI,GAAY,CAAC;QACjB,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,CAAC,iDAAiD;QAC7D,CAAC;QACD,MAAM,CAAC,GAAG,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,CAAC,OAAO;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,kDAAkD;IAClD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;AAC1C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expxdev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "CLI do metodo Expx: instala, atualiza e opera o ecossistema de skills, e sobe o painel de operacao",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"dependencies": {
|
|
32
|
+
"@inquirer/prompts": "^8.7.0",
|
|
32
33
|
"chokidar": "^5.0.0",
|
|
33
34
|
"ws": "^8.18.0",
|
|
34
35
|
"yaml": "^2.5.0",
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
"@types/react": "^18.3.0",
|
|
42
43
|
"@types/react-dom": "^18.3.0",
|
|
43
44
|
"@types/ws": "^8.5.0",
|
|
44
|
-
"@vitejs/plugin-react": "^
|
|
45
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
45
46
|
"gray-matter": "^4.0.3",
|
|
46
47
|
"jsdom": "^25.0.0",
|
|
47
48
|
"react": "^18.3.1",
|