@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
@@ -4,7 +4,7 @@ import { platform, totalmem, freemem, arch } from "os";
4
4
  import { existsSync } from "fs";
5
5
  import type { Command } from "./Command";
6
6
  import type { AppConfig, CLIArguments } from "../types/config";
7
- import { Logger } from "../utils/ui";
7
+ import { Logger, C } from "../utils/ui";
8
8
 
9
9
  const execAsync = promisify(exec);
10
10
 
@@ -50,16 +50,16 @@ export class HealthCommand implements Command {
50
50
 
51
51
  for (const check of checks) {
52
52
  const icon = check.status === "ok"
53
- ? `${Logger.C.success}✓${Logger.C.reset}`
53
+ ? `${C.success}✓${C.reset}`
54
54
  : check.status === "warning"
55
- ? `${Logger.C.warning}⚠${Logger.C.reset}`
56
- : `${Logger.C.error}✗${Logger.C.reset}`;
55
+ ? `${C.warning}⚠${C.reset}`
56
+ : `${C.error}✗${C.reset}`;
57
57
 
58
- Logger.log(`${Logger.C.gray}│${Logger.C.reset} ${icon} ${Logger.C.bold}${check.name}${Logger.C.reset}`);
59
- Logger.log(`${Logger.C.gray}│${Logger.C.reset} ${check.message}`);
58
+ Logger.log(`${C.gray}│${C.reset} ${icon} ${C.bold}${check.name}${C.reset}`);
59
+ Logger.log(`${C.gray}│${C.reset} ${check.message}`);
60
60
 
61
61
  if (check.details) {
62
- Logger.log(`${Logger.C.gray}│${Logger.C.reset} ${Logger.C.dim}${check.details}${Logger.C.reset}`);
62
+ Logger.log(`${C.gray}│${C.reset} ${C.dim}${check.details}${C.reset}`);
63
63
  }
64
64
 
65
65
  if (check.status === "error") errors++;
@@ -1,8 +1,11 @@
1
1
  import type { Command } from "./Command";
2
2
  import type { AppConfig, CLIArguments } from "../types/config";
3
3
  import pkg from "../../package.json";
4
+ import { Logger } from "../logging";
4
5
 
5
6
  export class HelpCommand implements Command {
7
+ private logger = Logger.getInstance();
8
+
6
9
  async execute(_config: AppConfig, _args?: CLIArguments): Promise<void> {
7
10
  const v = pkg.version;
8
11
  const c = this.c;
@@ -18,6 +21,7 @@ export class HelpCommand implements Command {
18
21
  ${c("green", "deploy")} Build and deploy to Tomcat
19
22
  ${c("green", "build")} Compile project
20
23
  ${c("green", "start")} Start Tomcat server
24
+ ${c("green", "clean")} Clean cache, build, and logs
21
25
  ${c("green", "run")} Run a Java class
22
26
  ${c("green", "logs")} Stream Tomcat logs
23
27
 
@@ -37,27 +41,42 @@ export class HelpCommand implements Command {
37
41
  ${c("magenta", "redo")} Repeat last command
38
42
  ${c("magenta", "completion")} Shell completions
39
43
 
40
- ${c("yellow", "NEW v3.1")}
41
- ${c("brightMagenta", "test")} Run JUnit/TestNG tests (--watch, --coverage)
42
- ${c("brightMagenta", "db")} Database migrations (Flyway/Liquibase)
44
+ ${c("yellow", "TESTING & DB")}
45
+ ${c("brightMagenta", "test")} Run JUnit/TestNG tests
46
+ ${c("brightMagenta", "db")} Database migrations
43
47
  ${c("brightMagenta", "http")} HTTP client for API testing
44
48
  ${c("brightMagenta", "docker")} Docker integration
45
49
 
50
+ ${c("yellow", "ADVANCED")}
51
+ ${c("blue", "ide")} Generate IDE config (vscode|idea|eclipse)
52
+ ${c("blue", "docs")} Generate API documentation
53
+ ${c("blue", "changelog")} Generate changelog from git
54
+
46
55
  ${c("yellow", "GLOBAL OPTIONS")}
47
- -p, --path <path> Tomcat path --port <n> Port (8080)
48
- -t, --tool <tool> maven|gradle -P, --profile <p> Build profile
49
- -n, --name <name> App name -e, --encoding <enc> UTF-8|cp1252
50
- -w, --watch Watch mode --tui Dashboard
51
- -d, --debug JPDA debugger -c, --clean Clean build
52
- -W, --war Build .war --env <name> Environment
53
- -h, --help Show help -v, --version Version
56
+ -p, --path <path> Tomcat path --port <n> Port (8080)
57
+ -t, --tool <tool> maven|gradle -P, --profile <p> Build profile
58
+ -n, --name <name> App name -e, --encoding <enc> UTF-8|cp1252
59
+ -w, --watch Watch mode --tui Dashboard mode
60
+ -d, --debug JPDA debugger -c, --clean Clean build
61
+ -W, --war Build .war --cache Use build cache
62
+ --env <name> Environment -y, --yes Auto-install
63
+ --profile Show performance --dry-run Simulate only
64
+ -V, --verbose Detailed output -h, --help Show help
65
+ -v, --version Show version
54
66
 
55
67
  ${c("yellow", "EXAMPLES")}
56
- xavva dev --tui --watch # Dev mode with dashboard
57
- xavva deploy --war --port 8081 # Build WAR for port 8081
58
- xavva test --watch # Test watch mode
59
- xavva deps --update-safe # Update dependencies
68
+ xavva dev --tui --watch # Dev mode with dashboard
69
+ xavva deploy --war --port 8081 # Build WAR for port 8081
70
+ xavva clean # Clean cache and build
71
+ xavva test --watch --coverage # Test with coverage
72
+ xavva doctor --fix # Auto-fix issues
73
+ xavva ide --ide vscode # Generate VS Code config
74
+ xavva deps --update-safe # Update dependencies
75
+ xavva deploy --dry-run # Simulate deployment
76
+ xavva build --profile # Show performance profile
60
77
  xavva docker init && xavva docker up # Docker setup
78
+ xavva tomcat install 10.1.52 --mirror auto # Install with best mirror
79
+ xavva tomcat cache stats # Show download cache stats
61
80
 
62
81
  ${c("gray", "Run 'xavva <command> --help' for detailed options")}
63
82
  ${c("gray", "Docs: github.com/leorsousa05/Xavva")}
@@ -74,6 +93,7 @@ export class HelpCommand implements Command {
74
93
  green: "\x1b[32m",
75
94
  yellow: "\x1b[33m",
76
95
  blue: "\x1b[34m",
96
+ magenta: "\x1b[35m",
77
97
  cyan: "\x1b[36m",
78
98
  brightMagenta: "\x1b[95m",
79
99
  };
@@ -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
 
6
6
  export class HistoryCommand implements Command {
7
7
  private historyService = new HistoryService();
@@ -33,13 +33,13 @@ export class HistoryCommand implements Command {
33
33
  const date = new Date(entry.timestamp);
34
34
  const time = date.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" });
35
35
  const icon = entry.success
36
- ? `${Logger.C.success}✓${Logger.C.reset}`
37
- : `${Logger.C.error}✗${Logger.C.reset}`;
36
+ ? `${C.success}✓${C.reset}`
37
+ : `${C.error}✗${C.reset}`;
38
38
 
39
39
  const args = entry.args.length > 0 ? entry.args.join(" ") : "";
40
- const duration = entry.duration ? `${Logger.C.gray}(${entry.duration.toFixed(1)}s)${Logger.C.reset}` : "";
40
+ const duration = entry.duration ? `${C.gray}(${entry.duration.toFixed(1)}s)${C.reset}` : "";
41
41
 
42
- Logger.log(`${Logger.C.gray}│${Logger.C.reset} ${Logger.C.dim}${time}${Logger.C.reset} ${icon} ${Logger.C.white}xavva ${entry.command}${Logger.C.reset} ${Logger.C.gray}${args}${Logger.C.reset} ${duration}`);
42
+ Logger.log(`${C.gray}│${C.reset} ${C.dim}${time}${C.reset} ${icon} ${C.white}xavva ${entry.command}${C.reset} ${C.gray}${args}${C.reset} ${duration}`);
43
43
  }
44
44
 
45
45
  Logger.endSection();
@@ -8,7 +8,7 @@ import type { Command } from "./Command";
8
8
  import type { AppConfig, CLIArguments } from "../types/config";
9
9
  import { HttpService, type HttpRequest } from "../services/HttpService";
10
10
  import { EndpointService } from "../services/EndpointService";
11
- import { Logger } from "../utils/ui";
11
+ import { Logger, C } from "../utils/ui";
12
12
  import { ProcessManager } from "../utils/processManager";
13
13
  import fs from "fs";
14
14
  import path from "path";
@@ -16,19 +16,19 @@ import path from "path";
16
16
  export class HttpCommand implements Command {
17
17
  private showHelp(): void {
18
18
  Logger.section("HTTP Client");
19
- Logger.log(`${Logger.C.bold}Usage:${Logger.C.reset} xavva http <method> <path> [options]`);
20
- Logger.log(`${Logger.C.bold} or:${Logger.C.reset} xavva http --interactive`);
19
+ Logger.log(`${C.bold}Usage:${C.reset} xavva http <method> <path> [options]`);
20
+ Logger.log(`${C.bold} or:${C.reset} xavva http --interactive`);
21
21
  Logger.newline();
22
- Logger.log(`${Logger.C.bold}Methods:${Logger.C.reset} GET, POST, PUT, DELETE, PATCH`);
22
+ Logger.log(`${C.bold}Methods:${C.reset} GET, POST, PUT, DELETE, PATCH`);
23
23
  Logger.newline();
24
- Logger.log(`${Logger.C.bold}Options:${Logger.C.reset}`);
24
+ Logger.log(`${C.bold}Options:${C.reset}`);
25
25
  Logger.log(` --body <data> Request body (JSON)`);
26
26
  Logger.log(` --param <k=v> Query parameter (can use multiple)`);
27
27
  Logger.log(` --header <h> Custom header`);
28
28
  Logger.log(` --base-url <url> Override base URL`);
29
29
  Logger.log(` -i, --interactive Interactive mode`);
30
30
  Logger.newline();
31
- Logger.log(`${Logger.C.bold}Examples:${Logger.C.reset}`);
31
+ Logger.log(`${C.bold}Examples:${C.reset}`);
32
32
  Logger.log(` xavva http GET /api/users`);
33
33
  Logger.log(` xavva http POST /api/users --body '{"name":"John"}'`);
34
34
  Logger.log(` xavva http GET /api/users --param page=1 --param size=10`);
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Comando IDE - Gera configurações para editores
3
+ *
4
+ * Suporta:
5
+ * - VS Code (.vscode/)
6
+ * - IntelliJ IDEA (.idea/)
7
+ * - Eclipse (.settings/)
8
+ */
9
+
10
+ import { mkdir, writeFile } from "fs/promises";
11
+ import { existsSync } from "fs";
12
+ import path from "path";
13
+ import type { Command } from "./Command";
14
+ import type { AppConfig, CLIArguments } from "../types/config";
15
+ import { Logger } from "../logging";
16
+
17
+ interface IdeConfig {
18
+ name: string;
19
+ files: Array<{
20
+ path: string;
21
+ content: string;
22
+ }>;
23
+ }
24
+
25
+ export class IdeCommand implements Command {
26
+ private logger = Logger.getInstance();
27
+
28
+ async execute(config: AppConfig, args: CLIArguments): Promise<void> {
29
+ const ide = (args as any).ide as 'vscode' | 'idea' | 'eclipse' | undefined;
30
+
31
+ if (!ide) {
32
+ this.logger.error("Especifique a IDE: --ide vscode|idea|eclipse");
33
+ return;
34
+ }
35
+
36
+ this.logger.section(`Gerando configuração para ${ide.toUpperCase()}`);
37
+
38
+ switch (ide) {
39
+ case 'vscode':
40
+ await this.generateVSCode(config);
41
+ break;
42
+ case 'idea':
43
+ await this.generateIdea(config);
44
+ break;
45
+ case 'eclipse':
46
+ await this.generateEclipse(config);
47
+ break;
48
+ default:
49
+ this.logger.error(`IDE não suportada: ${ide}`);
50
+ }
51
+ }
52
+
53
+ private async generateVSCode(config: AppConfig): Promise<void> {
54
+ const vscodeDir = path.join(process.cwd(), ".vscode");
55
+
56
+ // launch.json - Configuração de debug
57
+ const launchConfig = {
58
+ version: "0.2.0",
59
+ configurations: [
60
+ {
61
+ type: "java",
62
+ name: "Debug (Attach) - Xavva",
63
+ request: "attach",
64
+ hostName: "localhost",
65
+ port: config.project.debugPort,
66
+ },
67
+ {
68
+ type: "java",
69
+ name: "Debug (Launch) - Current File",
70
+ request: "launch",
71
+ mainClass: "${file}",
72
+ },
73
+ ],
74
+ };
75
+
76
+ // tasks.json - Tarefas de build
77
+ const tasksConfig = {
78
+ version: "2.0.0",
79
+ tasks: [
80
+ {
81
+ label: "xavva: build",
82
+ type: "shell",
83
+ command: "xavva build",
84
+ group: "build",
85
+ problemMatcher: ["$javac"],
86
+ },
87
+ {
88
+ label: "xavva: deploy",
89
+ type: "shell",
90
+ command: "xavva deploy",
91
+ group: "build",
92
+ problemMatcher: ["$javac"],
93
+ },
94
+ {
95
+ label: "xavva: dev",
96
+ type: "shell",
97
+ command: "xavva dev",
98
+ group: "build",
99
+ isBackground: true,
100
+ problemMatcher: {
101
+ pattern: {
102
+ regexp: ".",
103
+ },
104
+ background: {
105
+ activeOnStart: true,
106
+ beginsPattern: ".",
107
+ endsPattern: ".",
108
+ },
109
+ },
110
+ },
111
+ {
112
+ label: "xavva: test",
113
+ type: "shell",
114
+ command: "xavva test",
115
+ group: "test",
116
+ },
117
+ ],
118
+ };
119
+
120
+ // settings.json - Configurações do workspace
121
+ const settingsConfig = {
122
+ "java.configuration.updateBuildConfiguration": "automatic",
123
+ "java.compile.nullAnalysis.mode": "automatic",
124
+ "editor.formatOnSave": true,
125
+ "files.exclude": {
126
+ "**/target": true,
127
+ "**/build": true,
128
+ "**/.xavva": true,
129
+ "**/.gradle": true,
130
+ },
131
+ };
132
+
133
+ // extensions.json - Recomendações
134
+ const extensionsConfig = {
135
+ recommendations: [
136
+ "vscjava.vscode-java-pack",
137
+ "vscjava.vscode-java-debug",
138
+ "vscjava.vscode-maven",
139
+ "redhat.vscode-xml",
140
+ ],
141
+ };
142
+
143
+ await mkdir(vscodeDir, { recursive: true });
144
+
145
+ await writeFile(
146
+ path.join(vscodeDir, "launch.json"),
147
+ JSON.stringify(launchConfig, null, 4)
148
+ );
149
+ await writeFile(
150
+ path.join(vscodeDir, "tasks.json"),
151
+ JSON.stringify(tasksConfig, null, 4)
152
+ );
153
+ await writeFile(
154
+ path.join(vscodeDir, "settings.json"),
155
+ JSON.stringify(settingsConfig, null, 4)
156
+ );
157
+ await writeFile(
158
+ path.join(vscodeDir, "extensions.json"),
159
+ JSON.stringify(extensionsConfig, null, 4)
160
+ );
161
+
162
+ this.logger.success("Configuração VS Code gerada!");
163
+ this.logger.info("Arquivos criados:");
164
+ this.logger.info(" • .vscode/launch.json - Configuração de debug");
165
+ this.logger.info(" • .vscode/tasks.json - Tarefas de build");
166
+ this.logger.info(" • .vscode/settings.json - Configurações do workspace");
167
+ this.logger.info(" • .vscode/extensions.json - Extensões recomendadas");
168
+ this.logger.newline();
169
+ this.logger.info("💡 Instale as extensões recomendadas para melhor experiência");
170
+ }
171
+
172
+ private async generateIdea(config: AppConfig): Promise<void> {
173
+ const ideaDir = path.join(process.cwd(), ".idea");
174
+ const runConfigsDir = path.join(ideaDir, "runConfigurations");
175
+
176
+ // runConfigurations/Xavva_Deploy.xml
177
+ const deployConfig = `<component name="ProjectRunConfigurationManager">
178
+ <configuration default="false" name="Xavva - Deploy" type="ShConfigurationType">
179
+ <option name="SCRIPT_TEXT" value="xavva deploy" />
180
+ <option name="INDEPENDENT_SCRIPT_PATH" value="true" />
181
+ <option name="SCRIPT_PATH" value="" />
182
+ <option name="SCRIPT_OPTIONS" value="" />
183
+ <option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
184
+ <option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
185
+ <option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
186
+ <option name="INTERPRETER_PATH" value="" />
187
+ <option name="INTERPRETER_OPTIONS" value="" />
188
+ <option name="EXECUTE_IN_TERMINAL" value="true" />
189
+ <option name="EXECUTE_SCRIPT_FILE" value="false" />
190
+ <envs />
191
+ <method v="2" />
192
+ </configuration>
193
+ </component>`;
194
+
195
+ // runConfigurations/Xavva_Dev.xml
196
+ const devConfig = `<component name="ProjectRunConfigurationManager">
197
+ <configuration default="false" name="Xavva - Dev Mode" type="ShConfigurationType">
198
+ <option name="SCRIPT_TEXT" value="xavva dev" />
199
+ <option name="INDEPENDENT_SCRIPT_PATH" value="true" />
200
+ <option name="SCRIPT_PATH" value="" />
201
+ <option name="SCRIPT_OPTIONS" value="" />
202
+ <option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
203
+ <option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
204
+ <option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
205
+ <option name="INTERPRETER_PATH" value="" />
206
+ <option name="INTERPRETER_OPTIONS" value="" />
207
+ <option name="EXECUTE_IN_TERMINAL" value="true" />
208
+ <option name="EXECUTE_SCRIPT_FILE" value="false" />
209
+ <envs />
210
+ <method v="2" />
211
+ </configuration>
212
+ </component>`;
213
+
214
+ // External Tools - xavva.xml
215
+ const externalTools = `<toolSet name="Xavva">
216
+ <tool name="Build" showInMainMenu="false" showInEditor="false" showInProject="false" disabled="false" useConsole="true" showConsoleOnStdOut="false" showConsoleOnStdErr="false" synchronizeAfterRun="true">
217
+ <exec>
218
+ <option name="COMMAND" value="xavva" />
219
+ <option name="PARAMETERS" value="build" />
220
+ <option name="WORKING_DIRECTORY" value="$ProjectFileDir$" />
221
+ </exec>
222
+ </tool>
223
+ <tool name="Deploy" showInMainMenu="false" showInEditor="false" showInProject="false" disabled="false" useConsole="true" showConsoleOnStdOut="false" showConsoleOnStdErr="false" synchronizeAfterRun="true">
224
+ <exec>
225
+ <option name="COMMAND" value="xavva" />
226
+ <option name="PARAMETERS" value="deploy" />
227
+ <option name="WORKING_DIRECTORY" value="$ProjectFileDir$" />
228
+ </exec>
229
+ </tool>
230
+ </toolSet>`;
231
+
232
+ await mkdir(runConfigsDir, { recursive: true });
233
+ await mkdir(path.join(ideaDir, "externalTools"), { recursive: true });
234
+
235
+ await writeFile(path.join(runConfigsDir, "Xavva_Deploy.xml"), deployConfig);
236
+ await writeFile(path.join(runConfigsDir, "Xavva_Dev.xml"), devConfig);
237
+ await writeFile(
238
+ path.join(ideaDir, "externalTools", "xavva.xml"),
239
+ externalTools
240
+ );
241
+
242
+ this.logger.success("Configuração IntelliJ IDEA gerada!");
243
+ this.logger.info("Arquivos criados:");
244
+ this.logger.info(" • .idea/runConfigurations/Xavva_Deploy.xml");
245
+ this.logger.info(" • .idea/runConfigurations/Xavva_Dev.xml");
246
+ this.logger.info(" • .idea/externalTools/xavva.xml");
247
+ this.logger.newline();
248
+ this.logger.info("💡 Reinicie o IntelliJ para carregar as configurações");
249
+ }
250
+
251
+ private async generateEclipse(config: AppConfig): Promise<void> {
252
+ const settingsDir = path.join(process.cwd(), ".settings");
253
+
254
+ // External tool builders
255
+ const builderConfig = `<?xml version="1.0" encoding="UTF-8"?>
256
+ <projectDescription>
257
+ <name>${config.project.appName || "project"}</name>
258
+ <comment></comment>
259
+ <projects>
260
+ </projects>
261
+ <buildSpec>
262
+ <buildCommand>
263
+ <name>org.eclipse.jdt.core.javabuilder</name>
264
+ <arguments>
265
+ </arguments>
266
+ </buildCommand>
267
+ <buildCommand>
268
+ <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
269
+ <triggers>full,incremental,</triggers>
270
+ <arguments>
271
+ <dictionary>
272
+ <key>LaunchConfigHandle</key>
273
+ <value>&lt;project&gt;/.externalToolBuilders/Xavva Deploy.launch</value>
274
+ </dictionary>
275
+ </arguments>
276
+ </buildCommand>
277
+ </buildSpec>
278
+ <natures>
279
+ <nature>org.eclipse.jdt.core.javanature</nature>
280
+ </natures>
281
+ </projectDescription>`;
282
+
283
+ // External tool launcher
284
+ const launcherConfig = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n' +
285
+ '<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">\n' +
286
+ ' <booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>\n' +
287
+ ' <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="xavva"/>\n' +
288
+ ' <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="deploy"/>\n' +
289
+ ' <booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>\n' +
290
+ ' <stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/${project_name}}"/>\n' +
291
+ '</launchConfiguration>';
292
+
293
+ const externalToolsDir = path.join(process.cwd(), ".externalToolBuilders");
294
+ await mkdir(externalToolsDir, { recursive: true });
295
+ await mkdir(settingsDir, { recursive: true });
296
+
297
+ await writeFile(
298
+ path.join(process.cwd(), ".project"),
299
+ builderConfig
300
+ );
301
+ await writeFile(
302
+ path.join(externalToolsDir, "Xavva Deploy.launch"),
303
+ launcherConfig
304
+ );
305
+
306
+ this.logger.success("Configuração Eclipse gerada!");
307
+ this.logger.info("Arquivos criados:");
308
+ this.logger.info(" • .project");
309
+ this.logger.info(" • .externalToolBuilders/Xavva Deploy.launch");
310
+ this.logger.newline();
311
+ this.logger.info("💡 Importe o projeto como 'Existing Projects into Workspace'");
312
+ }
313
+ }
@@ -4,14 +4,15 @@ import { join } from "path";
4
4
  import { constants, existsSync } from "fs";
5
5
  import type { Command } from "./Command";
6
6
  import type { AppConfig, CLIArguments } from "../types/config";
7
- import { Logger } from "../utils/ui";
7
+ import { Logger } from "../logging";
8
8
 
9
9
  export class InitCommand implements Command {
10
+ private logger = Logger.getInstance();
11
+
10
12
  async execute(_config: AppConfig, _args?: CLIArguments): Promise<void> {
11
- Logger.banner("init");
12
- Logger.section("Project Setup Wizard");
13
- Logger.info("Let's configure your Xavva project");
14
- Logger.newline();
13
+ this.logger.section("Project Setup Wizard");
14
+ this.logger.info("Vamos configurar seu projeto Xavva");
15
+ this.logger.newline();
15
16
 
16
17
  // Detect build tool and available profiles
17
18
  const buildTool = await this.detectBuildTool();
@@ -25,9 +26,9 @@ export class InitCommand implements Command {
25
26
  });
26
27
 
27
28
  // Profile selection with explanation
28
- Logger.newline();
29
- Logger.dim("The profile is used to activate Maven/Gradle build configurations");
30
- Logger.dim("(e.g., 'dev' for development, 'prod' for production)");
29
+ this.logger.newline();
30
+ console.log("The profile is used to activate Maven/Gradle build configurations");
31
+ console.log("(e.g., 'dev' for development, 'prod' for production)");
31
32
 
32
33
  let profile: string;
33
34
 
@@ -76,8 +77,8 @@ export class InitCommand implements Command {
76
77
  }) || 8080;
77
78
 
78
79
  // Optional settings
79
- Logger.newline();
80
- Logger.dim("Advanced settings:");
80
+ this.logger.newline();
81
+ console.log("Advanced settings:");
81
82
 
82
83
  const useEmbedded = await confirm({
83
84
  message: "Use embedded Tomcat (auto-download)?",
@@ -150,8 +151,8 @@ export class InitCommand implements Command {
150
151
 
151
152
  // Add environments if enabled
152
153
  if (enableMultiEnv) {
153
- Logger.newline();
154
- Logger.dim("Environment Configuration:");
154
+ this.logger.newline();
155
+ console.log("Environment Configuration:");
155
156
 
156
157
  const environments: Record<string, unknown> = {};
157
158
 
@@ -213,20 +214,20 @@ export class InitCommand implements Command {
213
214
  }
214
215
 
215
216
  // Save file
216
- Logger.newline();
217
- Logger.step("Saving configuration...");
217
+ this.logger.newline();
218
+ this.logger.step("Saving configuration...");
218
219
 
219
220
  const configPath = join(process.cwd(), "xavva.json");
220
221
  await writeFile(configPath, JSON.stringify(config, null, 2));
221
222
 
222
- Logger.success(`Configuration saved to ${configPath}`);
223
- Logger.newline();
224
- Logger.ready("Project configured!");
225
- Logger.info("Next steps:");
226
- Logger.log(` ${Logger.C.gray}│${Logger.C.reset} ${Logger.C.primary}xavva build${Logger.C.reset} ${Logger.C.gray}- Compile project${Logger.C.reset}`);
227
- Logger.log(` ${Logger.C.gray}│${Logger.C.reset} ${Logger.C.primary}xavva deploy${Logger.C.reset} ${Logger.C.gray}- Build + deploy${Logger.C.reset}`);
228
- Logger.log(` ${Logger.C.gray}│${Logger.C.reset} ${Logger.C.primary}xavva health${Logger.C.reset} ${Logger.C.gray}- Check environment${Logger.C.reset}`);
229
- Logger.done();
223
+ this.logger.success(`Configuration saved to ${configPath}`);
224
+ this.logger.newline();
225
+ this.logger.ready("Project configured!");
226
+ this.logger.info("Next steps:");
227
+ console.log(` xavva build - Compile project`);
228
+ console.log(` xavva deploy - Build + deploy`);
229
+ console.log(` xavva health - Check environment`);
230
+ this.logger.newline();
230
231
  }
231
232
 
232
233
  private async detectBuildTool(): Promise<"maven" | "gradle"> {
@@ -235,17 +236,17 @@ export class InitCommand implements Command {
235
236
  existsSync(join(process.cwd(), "build.gradle.kts"));
236
237
 
237
238
  if (hasPom && !hasGradle) {
238
- Logger.info("Detected: Maven project");
239
+ this.logger.info("Detected: Maven project");
239
240
  return "maven";
240
241
  }
241
242
 
242
243
  if (hasGradle && !hasPom) {
243
- Logger.info("Detected: Gradle project");
244
+ this.logger.info("Detected: Gradle project");
244
245
  return "gradle";
245
246
  }
246
247
 
247
248
  if (hasPom && hasGradle) {
248
- Logger.warn("Both pom.xml and build.gradle found");
249
+ this.logger.warn("Both pom.xml and build.gradle found");
249
250
  const choice = await select({
250
251
  message: "Select build tool:",
251
252
  choices: [
@@ -2,11 +2,13 @@ import type { Command } from "./Command";
2
2
  import type { AppConfig, CLIArguments } from "../types/config";
3
3
  import { DashboardService } from "../services/DashboardService";
4
4
  import { LogAnalyzer } from "../services/LogAnalyzer";
5
- import { Logger } from "../utils/ui";
5
+ import { Logger } from "../logging";
6
6
  import path from "path";
7
7
  import fs from "fs";
8
8
 
9
9
  export class LogsCommand implements Command {
10
+ private logger = Logger.getInstance();
11
+
10
12
  constructor(private dashboard?: DashboardService, private logAnalyzer?: LogAnalyzer) {}
11
13
 
12
14
  async execute(config: AppConfig, args?: CLIArguments): Promise<void> {
@@ -14,18 +16,18 @@ export class LogsCommand implements Command {
14
16
 
15
17
  if (!fs.existsSync(logPath)) {
16
18
  const errorMsg = `Arquivo de log não encontrado: ${logPath}`;
17
- if (this.dashboard) this.dashboard.log(Logger.C.red + errorMsg);
18
- else Logger.error(errorMsg);
19
+ if (this.dashboard) this.dashboard.log(errorMsg);
20
+ else this.logger.error(errorMsg);
19
21
  return;
20
22
  }
21
23
 
22
24
  const analyzer = this.logAnalyzer || new LogAnalyzer(config.project);
23
25
  const dashboard = this.dashboard || new DashboardService(config);
24
26
 
25
- dashboard.setStatus("LOGGING", Logger.C.green);
27
+ dashboard.setStatus("LOGGING", "running");
26
28
 
27
29
  if (args?.grep) {
28
- dashboard.log(`${Logger.C.dim}Filter:${Logger.C.reset} ${Logger.C.bold}${args.grep}${Logger.C.reset}`);
30
+ dashboard.log(`Filter: ${args.grep}`);
29
31
  }
30
32
 
31
33
  const stats = fs.statSync(logPath);
@@ -60,7 +62,7 @@ export class LogsCommand implements Command {
60
62
  currentSize = newStats.size;
61
63
  } else if (newStats.size < currentSize) {
62
64
  currentSize = newStats.size;
63
- dashboard.log(Logger.C.warning + "Arquivo de log foi resetado/rotacionado.");
65
+ dashboard.log("Arquivo de log foi resetado/rotacionado.");
64
66
  }
65
67
  }
66
68
  });