@archznn/xavva 3.1.3 → 3.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.
Files changed (80) hide show
  1. package/README.md +221 -12
  2. package/package.json +3 -2
  3. package/src/commands/AuditCommand.ts +12 -10
  4. package/src/commands/BuildCommand.ts +9 -7
  5. package/src/commands/ChangelogCommand.ts +5 -5
  6. package/src/commands/CleanCommand.ts +242 -0
  7. package/src/commands/CompletionCommand.ts +7 -7
  8. package/src/commands/DbCommand.ts +33 -31
  9. package/src/commands/DeployCommand.ts +252 -229
  10. package/src/commands/DepsCommand.ts +174 -174
  11. package/src/commands/DockerCommand.ts +14 -14
  12. package/src/commands/DoctorCommand.ts +252 -239
  13. package/src/commands/EncodingCommand.ts +19 -19
  14. package/src/commands/HealthCommand.ts +7 -7
  15. package/src/commands/HelpCommand.ts +34 -14
  16. package/src/commands/HistoryCommand.ts +5 -5
  17. package/src/commands/HttpCommand.ts +6 -6
  18. package/src/commands/IdeCommand.ts +313 -0
  19. package/src/commands/InitCommand.ts +26 -25
  20. package/src/commands/LogsCommand.ts +8 -6
  21. package/src/commands/ProfilesCommand.ts +6 -6
  22. package/src/commands/RedoCommand.ts +2 -2
  23. package/src/commands/RunCommand.ts +64 -24
  24. package/src/commands/StartCommand.ts +9 -7
  25. package/src/commands/TestCommand.ts +4 -4
  26. package/src/commands/TomcatCommand.ts +219 -100
  27. package/src/config/versions.ts +111 -9
  28. package/src/di/container.ts +239 -105
  29. package/src/errors/ErrorHandler.ts +23 -19
  30. package/src/errors/errorMessages.ts +235 -0
  31. package/src/index.ts +11 -3
  32. package/src/logging/FileLogger.ts +235 -0
  33. package/src/logging/Logger.ts +545 -0
  34. package/src/logging/OperationLogger.ts +296 -0
  35. package/src/logging/ProgressLogger.ts +187 -0
  36. package/src/logging/TableLogger.ts +246 -0
  37. package/src/logging/colors.ts +167 -0
  38. package/src/logging/constants.ts +176 -0
  39. package/src/logging/formatters.ts +337 -0
  40. package/src/logging/index.ts +93 -0
  41. package/src/logging/types.ts +64 -0
  42. package/src/plugins/PluginManager.ts +325 -0
  43. package/src/plugins/types.ts +82 -0
  44. package/src/services/AuditService.ts +5 -3
  45. package/src/services/BuildService.ts +15 -17
  46. package/src/services/DashboardService.ts +14 -3
  47. package/src/services/DbService.ts +35 -34
  48. package/src/services/DependencyAnalyzerService.ts +18 -18
  49. package/src/services/DependencyCacheService.ts +303 -0
  50. package/src/services/DeployWatcher.ts +127 -23
  51. package/src/services/DockerService.ts +3 -3
  52. package/src/services/EmbeddedTomcatService.ts +13 -12
  53. package/src/services/FileWatcher.ts +15 -7
  54. package/src/services/HttpService.ts +5 -5
  55. package/src/services/LogAnalyzer.ts +26 -22
  56. package/src/services/PerformanceProfiler.ts +267 -0
  57. package/src/services/ProjectService.ts +3 -0
  58. package/src/services/TestService.ts +3 -3
  59. package/src/services/TomcatService.ts +46 -25
  60. package/src/services/tomcat/TomcatBackupManager.ts +330 -0
  61. package/src/services/tomcat/TomcatChecksumVerifier.ts +211 -0
  62. package/src/services/tomcat/TomcatCompatibilityChecker.ts +298 -0
  63. package/src/services/tomcat/TomcatDownloadCache.ts +250 -0
  64. package/src/services/tomcat/TomcatDownloadService.ts +335 -0
  65. package/src/services/tomcat/TomcatInstallerService.ts +474 -0
  66. package/src/services/tomcat/TomcatMirrorManager.ts +181 -0
  67. package/src/services/tomcat/index.ts +36 -0
  68. package/src/services/tomcat/types.ts +120 -0
  69. package/src/types/args.ts +68 -1
  70. package/src/types/configSchema.ts +174 -0
  71. package/src/utils/ChangelogGenerator.ts +11 -11
  72. package/src/utils/LoggerLevel.ts +44 -20
  73. package/src/utils/ProgressBar.ts +87 -46
  74. package/src/utils/argsParser.ts +260 -0
  75. package/src/utils/config.ts +340 -189
  76. package/src/utils/constants.ts +87 -9
  77. package/src/utils/dryRun.ts +192 -0
  78. package/src/utils/processManager.ts +23 -7
  79. package/src/utils/security.ts +293 -0
  80. package/src/utils/ui.ts +299 -428
@@ -1,7 +1,7 @@
1
1
  import type { Command } from "./Command";
2
2
  import type { AppConfig, CLIArguments } from "../types/config";
3
3
  import { ProjectService } from "../services/ProjectService";
4
- import { Logger } from "../utils/ui";
4
+ import { Logger, C } from "../utils/ui";
5
5
 
6
6
  export class ProfilesCommand implements Command {
7
7
  constructor(private projectService: ProjectService) {}
@@ -15,18 +15,18 @@ export class ProfilesCommand implements Command {
15
15
 
16
16
  if (profiles.length === 0) {
17
17
  Logger.warn("Nenhum perfil específico encontrado no arquivo de configuração.");
18
- Logger.log(` ${Logger.C.dim}Dica: Perfis Maven são definidos em <profiles> no pom.xml.${Logger.C.reset}`);
18
+ Logger.log(` ${C.dim}Dica: Perfis Maven são definidos em <profiles> no pom.xml.${C.reset}`);
19
19
  return;
20
20
  }
21
21
 
22
22
  Logger.log(`
23
- ${Logger.C.primary}Perfis detectados:${Logger.C.reset}`);
23
+ ${C.primary}Perfis detectados:${C.reset}`);
24
24
  profiles.forEach(p => {
25
- const active = config.project.profile === p ? ` ${Logger.C.green}(Ativo)${Logger.C.reset}` : "";
26
- Logger.log(` ${Logger.C.bold}➜${Logger.C.reset} ${p}${active}`);
25
+ const active = config.project.profile === p ? ` ${C.success}(Ativo)${C.reset}` : "";
26
+ Logger.log(` ${C.bold}➜${C.reset} ${p}${active}`);
27
27
  });
28
28
 
29
29
  Logger.newline();
30
- Logger.log(` ${Logger.C.dim}Para usar um perfil: xavva build -P nome-do-perfil${Logger.C.reset}`);
30
+ Logger.log(` ${C.dim}Para usar um perfil: xavva build -P nome-do-perfil${C.reset}`);
31
31
  }
32
32
  }
@@ -1,7 +1,7 @@
1
1
  import type { Command } from "./Command";
2
2
  import type { AppConfig, CLIArguments } from "../types/config";
3
3
  import { HistoryService } from "../services/HistoryService";
4
- import { Logger } from "../utils/ui";
4
+ import { Logger, C } from "../utils/ui";
5
5
  import { ProcessManager } from "../utils/processManager";
6
6
 
7
7
  export class RedoCommand implements Command {
@@ -17,7 +17,7 @@ export class RedoCommand implements Command {
17
17
 
18
18
  const args = lastEntry.args.length > 0 ? lastEntry.args.join(" ") : "";
19
19
  Logger.banner("redo");
20
- Logger.info(`Repetindo: ${Logger.C.white}xavva ${lastEntry.command}${Logger.C.reset} ${Logger.C.gray}${args}${Logger.C.reset}`);
20
+ Logger.info(`Repetindo: ${C.white}xavva ${lastEntry.command}${C.reset} ${C.gray}${args}${C.reset}`);
21
21
  Logger.newline();
22
22
 
23
23
  // Re-executar o comando
@@ -1,20 +1,25 @@
1
1
  import type { Command } from "./Command";
2
2
  import type { AppConfig, CLIArguments } from "../types/config";
3
- import { Logger } from "../utils/ui";
3
+ import { Logger } from "../logging";
4
4
  import path from "path";
5
5
  import fs from "fs";
6
6
  import { glob } from "glob";
7
7
  import readline from "readline";
8
+ import { BuildService } from "../services/BuildService";
8
9
  import {
9
- getJavaPath,
10
- getMavenCommand,
11
- getGradleCommand,
12
- getClasspathSeparator,
13
- normalizeClasspathPath,
14
- isWindows,
10
+ getJavaPath,
11
+ getMavenCommand,
12
+ getGradleCommand,
13
+ getClasspathSeparator,
14
+ normalizeClasspathPath,
15
+ isWindows,
15
16
  } from "../utils/platform";
16
17
 
17
18
  export class RunCommand implements Command {
19
+ private logger = Logger.getInstance();
20
+
21
+ constructor(private buildService?: BuildService) {}
22
+
18
23
  async execute(config: AppConfig, args?: CLIArguments): Promise<void> {
19
24
  const isDebug = args?.debug !== false; // Default to true if not specified, matching previous behavior
20
25
  let className = config.project.grep;
@@ -22,7 +27,7 @@ export class RunCommand implements Command {
22
27
  if (!className) {
23
28
  className = await this.loadFromHistory();
24
29
  if (!className) {
25
- Logger.error(`Uso: xavva ${isDebug ? "debug" : "run"} NomeDaClasse`);
30
+ this.logger.error(`Uso: xavva ${isDebug ? "debug" : "run"} NomeDaClasse`);
26
31
  return;
27
32
  }
28
33
  }
@@ -36,11 +41,14 @@ export class RunCommand implements Command {
36
41
  this.saveToHistory(className);
37
42
 
38
43
  if (isDebug) {
39
- Logger.section(`Interactive Debug: ${className}`);
44
+ this.logger.section(`Interactive Debug: ${className}`);
40
45
  } else {
41
- Logger.section(`Running: ${className}`);
46
+ this.logger.section(`Running: ${className}`);
42
47
  }
43
48
 
49
+ // Verifica se as classes estão compiladas, se não, compila
50
+ await this.ensureCompiled(config);
51
+
44
52
  const { localCp, dependencyCp } = await this.getClasspath(config);
45
53
  const pathingJar = await this.createPathingJar(dependencyCp);
46
54
 
@@ -62,11 +70,11 @@ export class RunCommand implements Command {
62
70
  javaArgs.push(className);
63
71
 
64
72
  if (isDebug) {
65
- Logger.warn(`🚀 Aguardando debugger na porta 5005 para ${className}...`);
66
- Logger.log(`${Logger.C.primary}Dica:${Logger.C.reset} No VS Code ou IntelliJ, use 'Attach to Remote JVM' na porta 5005.`);
67
- Logger.newline();
73
+ this.logger.warn(`🚀 Aguardando debugger na porta 5005 para ${className}...`);
74
+ console.log(`Dica: No VS Code ou IntelliJ, use 'Attach to Remote JVM' na porta 5005.`);
75
+ this.logger.newline();
68
76
  } else {
69
- Logger.warn(`🚀 Executando ${className}...`);
77
+ this.logger.warn(`🚀 Executando ${className}...`);
70
78
  }
71
79
 
72
80
  const bin = getJavaPath();
@@ -82,7 +90,7 @@ export class RunCommand implements Command {
82
90
  });
83
91
 
84
92
  await proc.exited;
85
- Logger.log(`Sessão de ${isDebug ? "debug" : "execução"} encerrada.`);
93
+ this.logger.info(`Sessão de ${isDebug ? "debug" : "execução"} encerrada.`);
86
94
  }
87
95
 
88
96
  private async discoverClass(simpleName: string): Promise<string | null> {
@@ -124,7 +132,7 @@ export class RunCommand implements Command {
124
132
  }
125
133
  }
126
134
  if (files.length === 0) {
127
- Logger.error(`Classe "${simpleName}" não encontrada nos diretórios de código (src/main/java, src/test/java, src).`);
135
+ this.logger.error(`Classe "${simpleName}" não encontrada nos diretórios de código (src/main/java, src/test/java, src).`);
128
136
  return null;
129
137
  }
130
138
  }
@@ -143,9 +151,9 @@ export class RunCommand implements Command {
143
151
  return uniqueClasses[0];
144
152
  }
145
153
 
146
- Logger.warn(`Múltiplas classes encontradas para "${simpleName}":`);
154
+ this.logger.warn(`Múltiplas classes encontradas para "${simpleName}":`);
147
155
  uniqueClasses.forEach((c, i) => {
148
- Logger.log(` [${i + 1}] ${c}`);
156
+ console.log(` [${i + 1}] ${c}`);
149
157
  });
150
158
 
151
159
  const rl = readline.createInterface({
@@ -160,7 +168,7 @@ export class RunCommand implements Command {
160
168
  if (!isNaN(idx) && uniqueClasses[idx]) {
161
169
  resolve(uniqueClasses[idx]);
162
170
  } else {
163
- Logger.error("Operação cancelada.");
171
+ this.logger.error("Operação cancelada.");
164
172
  resolve(null);
165
173
  }
166
174
  });
@@ -177,9 +185,9 @@ export class RunCommand implements Command {
177
185
  const history: string[] = JSON.parse(fs.readFileSync(historyFile, "utf8"));
178
186
  if (history.length === 0) return null;
179
187
 
180
- Logger.warn(`Classes executadas recentemente:`);
188
+ this.logger.warn(`Classes executadas recentemente:`);
181
189
  history.slice(0, 5).forEach((c, i) => {
182
- Logger.log(` [${i + 1}] ${c}${i === 0 ? " (Enter)" : ""}`);
190
+ console.log(` [${i + 1}] ${c}${i === 0 ? " (Enter)" : ""}`);
183
191
  });
184
192
 
185
193
  const rl = readline.createInterface({
@@ -296,6 +304,38 @@ export class RunCommand implements Command {
296
304
  return jarPath;
297
305
  }
298
306
 
307
+ /**
308
+ * Verifica se as classes compiladas existem, se não, executa o build
309
+ * Usa build incremental (apenas compile, sem clean) para evitar conflitos
310
+ * com o Tomcat que pode estar rodando e usando arquivos em target/
311
+ */
312
+ private async ensureCompiled(config: AppConfig): Promise<void> {
313
+ // Usa build incremental (sem clean) para evitar problemas quando Tomcat está rodando
314
+ if (this.buildService) {
315
+ this.logger.step("Compilando projeto...");
316
+ await this.buildService.runBuild(true); // true = incremental, sem clean
317
+ } else {
318
+ // Fallback: executa build via comando direto (apenas compile, sem clean)
319
+ this.logger.step("Compilando projeto (fallback)...");
320
+ const buildCmd = config.project.buildTool === "maven"
321
+ ? [getMavenCommand(), "compile", "-DskipTests"]
322
+ : [getGradleCommand(), "classes", "-x", "test"];
323
+
324
+ const spinner = this.logger.spinner("Compilando");
325
+ const proc = Bun.spawn(buildCmd, {
326
+ stdout: "pipe",
327
+ stderr: "pipe",
328
+ });
329
+
330
+ await proc.exited;
331
+ spinner.stop();
332
+
333
+ if (proc.exitCode !== 0) {
334
+ throw new Error("Falha ao compilar o projeto. Verifique os erros acima.");
335
+ }
336
+ }
337
+ }
338
+
299
339
  private async getClasspath(config: AppConfig): Promise<{ localCp: string, dependencyCp: string }> {
300
340
  const xavvaDir = path.join(process.cwd(), ".xavva");
301
341
  const cpFile = path.join(xavvaDir, "classpath.txt");
@@ -303,7 +343,7 @@ export class RunCommand implements Command {
303
343
  if (!fs.existsSync(xavvaDir)) fs.mkdirSync(xavvaDir);
304
344
 
305
345
  if (!fs.existsSync(cpFile)) {
306
- const stopSpinner = Logger.spinner("Generating project classpath");
346
+ const spinner = this.logger.spinner("Generating project classpath");
307
347
  try {
308
348
  if (config.project.buildTool === "maven") {
309
349
  Bun.spawnSync([getMavenCommand(), "dependency:build-classpath", `-Dmdep.outputFile=${cpFile}`]);
@@ -337,9 +377,9 @@ export class RunCommand implements Command {
337
377
  fs.writeFileSync(cpFile, ".");
338
378
  }
339
379
  } catch (e) {
340
- Logger.error(`Falha ao gerar classpath: ${e}`);
380
+ this.logger.error(`Falha ao gerar classpath: ${e}`);
341
381
  }
342
- stopSpinner();
382
+ spinner.stop();
343
383
  }
344
384
 
345
385
  let dependencyCp = fs.existsSync(cpFile) ? fs.readFileSync(cpFile, "utf8").trim() : "";
@@ -1,29 +1,31 @@
1
1
  import type { Command } from "./Command";
2
2
  import type { AppConfig } from "../types/config";
3
3
  import { TomcatService } from "../services/TomcatService";
4
- import { Logger } from "../utils/ui";
4
+ import { Logger } from "../logging";
5
5
  import { ProcessManager } from "../utils/processManager";
6
6
 
7
7
  export class StartCommand implements Command {
8
+ private logger = Logger.getInstance();
9
+
8
10
  constructor(private tomcat: TomcatService) {}
9
11
 
10
12
  async execute(config: AppConfig): Promise<void> {
11
13
  const tomcat = this.tomcat;
12
14
 
13
- Logger.section("Start Only");
14
- Logger.info("Port", config.tomcat.port);
15
- if (config.project.debug) Logger.info("Debugger", "Active (5005)");
15
+ this.logger.section("Start Only");
16
+ this.logger.config("Port", config.tomcat.port);
17
+ if (config.project.debug) this.logger.config("Debugger", "Active (5005)");
16
18
 
17
19
  try {
18
- Logger.step("Checking ports");
20
+ this.logger.step("Checking ports");
19
21
  await tomcat.killConflict();
20
- Logger.step("Starting Tomcat");
22
+ this.logger.step("Starting Tomcat");
21
23
  tomcat.start(config, false);
22
24
 
23
25
  await new Promise(() => {});
24
26
  } catch (error) {
25
27
  const message = error instanceof Error ? error.message : String(error);
26
- Logger.error(message);
28
+ this.logger.error(message);
27
29
  await ProcessManager.getInstance().shutdown(1);
28
30
  }
29
31
  }
@@ -6,7 +6,7 @@
6
6
  import type { Command } from "./Command";
7
7
  import type { AppConfig, CLIArguments } from "../types/config";
8
8
  import { TestService } from "../services/TestService";
9
- import { Logger } from "../utils/ui";
9
+ import { Logger, C } from "../utils/ui";
10
10
  import { ProcessManager } from "../utils/processManager";
11
11
 
12
12
  export class TestCommand implements Command {
@@ -14,16 +14,16 @@ export class TestCommand implements Command {
14
14
 
15
15
  private showHelp(): void {
16
16
  Logger.section("Test Runner");
17
- Logger.log(`${Logger.C.bold}Usage:${Logger.C.reset} xavva test [options] [filter]`);
17
+ Logger.log(`${C.bold}Usage:${C.reset} xavva test [options] [filter]`);
18
18
  Logger.newline();
19
- Logger.log(`${Logger.C.bold}Options:${Logger.C.reset}`);
19
+ Logger.log(`${C.bold}Options:${C.reset}`);
20
20
  Logger.log(` -w, --watch Watch mode (run on file change)`);
21
21
  Logger.log(` --coverage Generate JaCoCo coverage report`);
22
22
  Logger.log(` --fail-fast Stop on first failure`);
23
23
  Logger.log(` --parallel Run tests in parallel`);
24
24
  Logger.log(` -V, --verbose Verbose output`);
25
25
  Logger.newline();
26
- Logger.log(`${Logger.C.bold}Examples:${Logger.C.reset}`);
26
+ Logger.log(`${C.bold}Examples:${C.reset}`);
27
27
  Logger.log(` xavva test # Run all tests`);
28
28
  Logger.log(` xavva test --watch # Watch mode`);
29
29
  Logger.log(` xavva test --coverage # With coverage`);