@archznn/xavva 2.0.0 β 2.0.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/README.md +1 -1
- package/package.json +1 -1
- package/src/commands/HelpCommand.ts +35 -37
- package/src/index.ts +9 -0
- package/src/services/DashboardService.ts +26 -20
- package/src/utils/ui.ts +21 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# XAVVA π (Windows Only) `v2.0.
|
|
1
|
+
# XAVVA π (Windows Only) `v2.0.1`
|
|
2
2
|
|
|
3
3
|
Xavva Γ© uma CLI de alto desempenho construΓda com **Bun** para automatizar o ciclo de desenvolvimento de aplicaΓ§Γ΅es Java (Maven/Gradle) rodando no Apache Tomcat. Ela foi desenhada especificamente para desenvolvedores que buscam a velocidade de ambientes modernos (como Node.js/Vite) dentro do ecossistema Java Enterprise.
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -1,50 +1,48 @@
|
|
|
1
1
|
import type { Command } from "./Command";
|
|
2
|
-
import type { AppConfig } from "../types/config";
|
|
2
|
+
import type { AppConfig, CLIArguments } from "../types/config";
|
|
3
3
|
import pkg from "../../package.json";
|
|
4
4
|
|
|
5
5
|
export class HelpCommand implements Command {
|
|
6
|
-
async execute(_config: AppConfig): Promise<void> {
|
|
6
|
+
async execute(_config: AppConfig, _args?: CLIArguments): Promise<void> {
|
|
7
7
|
console.log(`
|
|
8
|
-
π οΈ
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
π οΈ XAVVA CLI v${pkg.version} π
|
|
9
|
+
---------------------------------------
|
|
10
|
+
AutomatizaΓ§Γ£o de alta performance para Java Enterprise (Tomcat) no Windows.
|
|
11
|
+
Detecta automaticamente Maven/Gradle e otimiza o ciclo de desenvolvimento.
|
|
12
12
|
|
|
13
13
|
Comandos principais:
|
|
14
|
-
dev π MODO COMPLETO: Deploy + Watch + Debug
|
|
15
|
-
deploy (PadrΓ£o)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
doctor π©Ί
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
debug π Debuga uma classe main (Uso: xavva debug NomeDaClasse).
|
|
23
|
-
logs π Monitora o catalina.out do Tomcat em tempo real.
|
|
14
|
+
dev π MODO COMPLETO: Build + Deploy + Watch + Debug.
|
|
15
|
+
deploy (PadrΓ£o) Compila, sincroniza e inicia o servidor.
|
|
16
|
+
logs π Tail inteligente (catalina.out) com Smart Folding.
|
|
17
|
+
run / debug π Executa classes standalone com Pathing JAR (Windows).
|
|
18
|
+
doctor π©Ί DiagnΓ³stico e reparo de ambiente (DCEVM, JAVA_HOME).
|
|
19
|
+
audit π‘οΈ Auditoria de seguranΓ§a em JARs via OSV.dev.
|
|
20
|
+
docs π Mapeamento estΓ‘tico de Endpoints e JSPs.
|
|
21
|
+
build / start Comandos granulares de compilaΓ§Γ£o ou startup.
|
|
24
22
|
|
|
25
|
-
OpΓ§Γ΅es:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
--
|
|
29
|
-
-c, --clean π§Ή Logs coloridos e simplificados (
|
|
30
|
-
-
|
|
31
|
-
-V, --verbose π£ Mostra logs completos do Maven/Gradle.
|
|
32
|
-
-s, --no-build Pula o build (usa o que jΓ‘ estiver na pasta target/build).
|
|
33
|
-
-P, --profile Define o profile (ex: -P prod).
|
|
34
|
-
--fix π§ Corrige problemas automaticamente no 'doctor'.
|
|
23
|
+
OpΓ§Γ΅es de Interface:
|
|
24
|
+
--tui π₯οΈ Ativa o Dashboard Interativo (Interface TUI).
|
|
25
|
+
No modo TUI use: [R] Restart, [L] Clear, [Q] Quit.
|
|
26
|
+
-w, --watch π Hot Reload: Redeploy incremental de classes e recursos.
|
|
27
|
+
-c, --clean π§Ή Logs coloridos e simplificados (Recomendado).
|
|
28
|
+
-V, --verbose π£ Exibe logs completos do Maven/Gradle.
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
xavva build -P dev Apenas compila usando o profile 'dev'.
|
|
30
|
+
OpΓ§Γ΅es de Runtime:
|
|
31
|
+
-d, --debug π Habilita JPDA Debugging (Porta 5005).
|
|
32
|
+
-P, --profile Define o profile de build (ex: -P prod).
|
|
33
|
+
-s, --no-build Pula o build inicial.
|
|
34
|
+
--fix π§ Corrige problemas automaticamente (Doctor).
|
|
42
35
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
-t,
|
|
46
|
-
|
|
47
|
-
|
|
36
|
+
ConfiguraΓ§Γ£o:
|
|
37
|
+
O Xavva prioriza o arquivo 'xavva.json' na raiz do projeto.
|
|
38
|
+
Flags de linha de comando: -p (Tomcat Path), -t (Build Tool), -n (WAR Name).
|
|
39
|
+
|
|
40
|
+
Exemplos:
|
|
41
|
+
xavva dev --tui ExperiΓͺncia completa com Dashboard.
|
|
42
|
+
xavva run MyClass ExecuΓ§Γ£o standalone com classpath automΓ‘tico.
|
|
43
|
+
xavva audit Verifica vulnerabilidades conhecidas.
|
|
44
|
+
|
|
45
|
+
*Transformando o legado em produtivo.*
|
|
48
46
|
`);
|
|
49
47
|
}
|
|
50
48
|
}
|
package/src/index.ts
CHANGED
|
@@ -55,6 +55,7 @@ async function main() {
|
|
|
55
55
|
// Xavva 2.0: Dashboard & LogAnalyzer
|
|
56
56
|
const logAnalyzer = new LogAnalyzer(config.project);
|
|
57
57
|
const dashboard = new DashboardService(config);
|
|
58
|
+
Logger.setDashboard(dashboard);
|
|
58
59
|
|
|
59
60
|
// 2. Registrar Comandos
|
|
60
61
|
const registry = new CommandRegistry();
|
|
@@ -75,6 +76,14 @@ async function main() {
|
|
|
75
76
|
|
|
76
77
|
// Caso especial: Watch Mode para Deploy/Dev
|
|
77
78
|
if ((commandName === "deploy" || commandName === "dev") && values.watch) {
|
|
79
|
+
// Registrar aΓ§Γ£o de restart manual na TUI
|
|
80
|
+
if (dashboard.isTuiActive()) {
|
|
81
|
+
dashboard.onAction("r", () => {
|
|
82
|
+
dashboard.log(Logger.C.yellow + "Restart manual solicitado via TUI...");
|
|
83
|
+
deployCmd.execute(config, false, true); // Executa deploy completo mas mantΓ©m o watch
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
78
87
|
const watcher = new WatcherService(config, deployCmd);
|
|
79
88
|
await watcher.start();
|
|
80
89
|
} else {
|
|
@@ -8,17 +8,29 @@ export class DashboardService {
|
|
|
8
8
|
private maxLogLines: number = 0;
|
|
9
9
|
private status: string = "IDLE";
|
|
10
10
|
private statusColor: string = Logger.C.dim;
|
|
11
|
+
private gitContext: any = null;
|
|
12
|
+
private actions: Map<string, () => void> = new Map();
|
|
11
13
|
|
|
12
14
|
constructor(private config: AppConfig) {
|
|
13
15
|
this.isTui = config.project.tui;
|
|
14
16
|
if (this.isTui) {
|
|
15
|
-
this.
|
|
17
|
+
this.gitContext = Logger.getGitContext();
|
|
18
|
+
this.maxLogLines = process.stdout.rows - 6;
|
|
16
19
|
this.setupTui();
|
|
17
20
|
}
|
|
18
21
|
}
|
|
19
22
|
|
|
23
|
+
public isTuiActive(): boolean {
|
|
24
|
+
return this.isTui;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public onAction(key: string, callback: () => void) {
|
|
28
|
+
this.actions.set(key.toLowerCase(), callback);
|
|
29
|
+
}
|
|
30
|
+
|
|
20
31
|
private setupTui() {
|
|
21
32
|
process.stdout.write("\x1B[?1049h"); // Switch to alternate buffer
|
|
33
|
+
process.stdout.write("\x1B[2J"); // Clear screen
|
|
22
34
|
process.stdout.write("\x1B[?25l"); // Hide cursor
|
|
23
35
|
|
|
24
36
|
process.stdin.setRawMode(true);
|
|
@@ -26,14 +38,19 @@ export class DashboardService {
|
|
|
26
38
|
process.stdin.setEncoding("utf8");
|
|
27
39
|
|
|
28
40
|
process.stdin.on("data", (key: string) => {
|
|
41
|
+
const input = key.toLowerCase();
|
|
29
42
|
// Ctrl+C ou Q para sair
|
|
30
|
-
if (key === "\u0003" ||
|
|
43
|
+
if (key === "\u0003" || input === "q") {
|
|
31
44
|
this.exit();
|
|
32
45
|
}
|
|
33
|
-
if (
|
|
46
|
+
if (input === "l") {
|
|
34
47
|
this.logLines = [];
|
|
35
48
|
this.render();
|
|
49
|
+
return;
|
|
36
50
|
}
|
|
51
|
+
|
|
52
|
+
const action = this.actions.get(input);
|
|
53
|
+
if (action) action();
|
|
37
54
|
});
|
|
38
55
|
|
|
39
56
|
process.on("SIGINT", () => this.exit());
|
|
@@ -43,14 +60,6 @@ export class DashboardService {
|
|
|
43
60
|
setInterval(() => this.render(), 1000);
|
|
44
61
|
}
|
|
45
62
|
|
|
46
|
-
public onKey(key: string, callback: () => void) {
|
|
47
|
-
process.stdin.on("data", (input: string) => {
|
|
48
|
-
if (input.toLowerCase() === key.toLowerCase()) {
|
|
49
|
-
callback();
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
63
|
public setStatus(status: string, color: string = Logger.C.cyan) {
|
|
55
64
|
this.status = status;
|
|
56
65
|
this.statusColor = color;
|
|
@@ -75,32 +84,29 @@ export class DashboardService {
|
|
|
75
84
|
private render() {
|
|
76
85
|
if (!this.isTui) return;
|
|
77
86
|
|
|
78
|
-
this.maxLogLines = process.stdout.rows -
|
|
87
|
+
this.maxLogLines = process.stdout.rows - 6;
|
|
79
88
|
|
|
80
89
|
let output = "\x1B[H"; // Move to 0,0
|
|
81
90
|
|
|
82
91
|
// Header
|
|
83
92
|
const name = (process.cwd().split(/[/\\]/).pop() || "PROJECT").toUpperCase();
|
|
84
|
-
const git = Logger.getGitContext();
|
|
85
93
|
const mem = Math.round((os.totalmem() - os.freemem()) / 1024 / 1024 / 1024 * 10) / 10;
|
|
86
94
|
const totalMem = Math.round(os.totalmem() / 1024 / 1024 / 1024);
|
|
87
95
|
|
|
88
|
-
output += `${Logger.C.bold}${Logger.C.cyan} X A V V A 2.0 ${Logger.C.reset} ${Logger.C.dim}β${Logger.C.reset} ${Logger.C.white}${Logger.C.bold}${name}${Logger.C.reset}\n`;
|
|
89
|
-
output += `${Logger.C.dim} STATUS: ${this.statusColor}${this.status.padEnd(10)}${Logger.C.reset} ${Logger.C.dim}β MEM: ${Logger.C.yellow}${mem}G/${totalMem}G${Logger.C.reset} ${Logger.C.dim}β BRANCH: ${Logger.C.magenta}${
|
|
90
|
-
output += `${Logger.C.dim}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ${Logger.C.reset}\n`;
|
|
96
|
+
output += `${Logger.C.bold}${Logger.C.cyan} X A V V A 2.0 ${Logger.C.reset} ${Logger.C.dim}β${Logger.C.reset} ${Logger.C.white}${Logger.C.bold}${name}${Logger.C.reset}\x1B[K\n`;
|
|
97
|
+
output += `${Logger.C.dim} STATUS: ${this.statusColor}${this.status.padEnd(10)}${Logger.C.reset} ${Logger.C.dim}β MEM: ${Logger.C.yellow}${mem}G/${totalMem}G${Logger.C.reset} ${Logger.C.dim}β BRANCH: ${Logger.C.magenta}${this.gitContext?.branch || "unknown"}${Logger.C.reset}\x1B[K\n`;
|
|
98
|
+
output += `${Logger.C.dim}ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ${Logger.C.reset}\x1B[K\n`;
|
|
91
99
|
|
|
92
100
|
// Logs
|
|
93
101
|
const visibleLogs = this.logLines.slice(-this.maxLogLines);
|
|
94
102
|
for (let i = 0; i < this.maxLogLines; i++) {
|
|
95
103
|
const line = visibleLogs[i] || "";
|
|
96
|
-
// Limpa a linha antes de escrever (ANSI escape EL)
|
|
97
104
|
output += line.substring(0, process.stdout.columns) + "\x1B[K\n";
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
// Footer
|
|
101
|
-
output += `\x1B[${process.stdout.rows
|
|
102
|
-
output +=
|
|
103
|
-
output += ` ${Logger.C.bold}${Logger.C.white}R${Logger.C.reset} Restart ${Logger.C.bold}${Logger.C.white}L${Logger.C.reset} Clear ${Logger.C.bold}${Logger.C.white}Q${Logger.C.reset} Quit ${Logger.C.dim} (Xavva 2.0 TUI Mode)${Logger.C.reset}`;
|
|
108
|
+
output += `\x1B[${process.stdout.rows};1H`; // Move to last row
|
|
109
|
+
output += ` ${Logger.C.bold}${Logger.C.white}R${Logger.C.reset} Restart ${Logger.C.bold}${Logger.C.white}L${Logger.C.reset} Clear ${Logger.C.bold}${Logger.C.white}Q${Logger.C.reset} Quit ${Logger.C.dim} (Xavva 2.0 TUI Mode)${Logger.C.reset}\x1B[K`;
|
|
104
110
|
|
|
105
111
|
process.stdout.write(output);
|
|
106
112
|
}
|
package/src/utils/ui.ts
CHANGED
|
@@ -22,8 +22,18 @@ export class Logger {
|
|
|
22
22
|
private static lastDomain = "";
|
|
23
23
|
private static lastHotswapMsg = "";
|
|
24
24
|
private static activeSpinnerMsg = "";
|
|
25
|
+
private static dashboard: any = null;
|
|
26
|
+
|
|
27
|
+
static setDashboard(dashboard: any) {
|
|
28
|
+
this.dashboard = dashboard;
|
|
29
|
+
}
|
|
25
30
|
|
|
26
31
|
private static write(message: string, isError: boolean = false) {
|
|
32
|
+
if (this.dashboard && this.dashboard.isTuiActive()) {
|
|
33
|
+
this.dashboard.log(message);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
if (this.activeSpinnerMsg) {
|
|
28
38
|
process.stdout.write("\r\x1B[K"); // Limpa a linha do spinner
|
|
29
39
|
}
|
|
@@ -126,6 +136,17 @@ export class Logger {
|
|
|
126
136
|
static dim(msg: string) { this.write(` ${this.C.dim}${msg}${this.C.reset}`); }
|
|
127
137
|
|
|
128
138
|
static spinner(msg: string) {
|
|
139
|
+
if (this.dashboard && this.dashboard.isTuiActive()) {
|
|
140
|
+
this.dashboard.log(`${this.C.cyan}β ${this.C.reset} ${msg}...`);
|
|
141
|
+
return (success = true) => {
|
|
142
|
+
if (success) {
|
|
143
|
+
this.dashboard.log(`${this.C.green}β${this.C.reset} ${msg}`);
|
|
144
|
+
} else {
|
|
145
|
+
this.dashboard.log(`${this.C.red}β${this.C.reset} Falha em ${msg}`);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
129
150
|
this.activeSpinnerMsg = msg;
|
|
130
151
|
const frames = ["β ", "β ", "β Ή", "β Έ", "β Ό", "β ΄", "β ¦", "β §", "β ", "β "];
|
|
131
152
|
let i = 0;
|