@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,4 +1,10 @@
1
- import { Logger } from "./ui";
1
+ /**
2
+ * ProgressBar - Adaptador para o novo sistema de logging
3
+ *
4
+ * @deprecated Use ProgressLogger de src/logging/
5
+ */
6
+
7
+ import { Logger, ProgressLogger, Colors } from "../logging";
2
8
 
3
9
  export interface ProgressBarOptions {
4
10
  title: string;
@@ -6,13 +12,18 @@ export interface ProgressBarOptions {
6
12
  width?: number;
7
13
  showPercentage?: boolean;
8
14
  showEta?: boolean;
15
+ showSpeed?: boolean;
9
16
  }
10
17
 
18
+ /**
19
+ * @deprecated Use ProgressLogger de src/logging/
20
+ */
11
21
  export class ProgressBar {
12
22
  private current = 0;
13
23
  private startTime: number;
14
24
  private options: Required<ProgressBarOptions>;
15
25
  private isComplete = false;
26
+ private logger: ProgressLogger;
16
27
 
17
28
  constructor(options: ProgressBarOptions) {
18
29
  this.options = {
@@ -22,12 +33,55 @@ export class ProgressBar {
22
33
  ...options
23
34
  };
24
35
  this.startTime = Date.now();
36
+
37
+ // Cria um ProgressLogger interno
38
+ this.logger = new ProgressLogger(options.title, {
39
+ total: options.total,
40
+ width: this.options.width,
41
+ showPercentage: this.options.showPercentage,
42
+ showEta: this.options.showEta,
43
+ });
25
44
  }
26
45
 
27
- update(current: number): void {
46
+ update(current: number, speed?: number, eta?: number): void {
28
47
  if (this.isComplete) return;
29
48
  this.current = Math.min(current, this.options.total);
30
- this.render();
49
+
50
+ // Atualiza o ProgressLogger interno com extras se disponíveis
51
+ if (speed !== undefined && eta !== undefined) {
52
+ // Cria string de extras
53
+ const extras: string[] = [];
54
+ if (this.options.showSpeed && speed > 0) {
55
+ extras.push(`${speed.toFixed(1)} MB/s`);
56
+ }
57
+ if (this.options.showEta && eta > 0) {
58
+ const etaSec = Math.ceil(eta);
59
+ if (etaSec < 60) {
60
+ extras.push(`${etaSec}s restantes`);
61
+ } else {
62
+ extras.push(`${Math.ceil(etaSec / 60)}min restantes`);
63
+ }
64
+ }
65
+
66
+ // Renderiza com extras
67
+ this.renderWithExtras(extras);
68
+ } else {
69
+ this.logger.update(this.current);
70
+ }
71
+ }
72
+
73
+ private renderWithExtras(extras: string[]): void {
74
+ // Acessa o método privado via cast para atualizar com extras
75
+ const percentage = Math.floor((this.current / this.options.total) * 100);
76
+ const filled = Math.floor((this.current / this.options.total) * this.options.width);
77
+ const empty = this.options.width - filled;
78
+
79
+ const bar = "█".repeat(filled) + "░".repeat(empty);
80
+ const extraStr = extras.length > 0 ? ` | ${extras.join(" | ")}` : "";
81
+
82
+ process.stdout.clearLine?.(0);
83
+ process.stdout.cursorTo?.(0);
84
+ process.stdout.write(` ${this.options.title}: [${bar}] ${percentage}%${extraStr}`);
31
85
  }
32
86
 
33
87
  increment(amount = 1): void {
@@ -38,54 +92,39 @@ export class ProgressBar {
38
92
  if (this.isComplete) return;
39
93
  this.current = this.options.total;
40
94
  this.isComplete = true;
41
- this.render();
42
- process.stdout.write("\n");
95
+
96
+ // Limpa linha e mostra completo
97
+ process.stdout.clearLine?.(0);
98
+ process.stdout.cursorTo?.(0);
99
+
100
+ this.logger.complete();
43
101
  }
44
102
 
45
103
  private render(): void {
46
- const { title, total, width, showPercentage, showEta } = this.options;
47
- const ratio = this.current / total;
48
- const filled = Math.floor(ratio * width);
49
- const empty = width - filled;
50
-
51
- const bar = "█".repeat(filled) + "░".repeat(empty);
52
- const percentage = Math.floor(ratio * 100);
53
-
54
- let line = `${Logger.C.gray}│${Logger.C.reset} ${Logger.C.primary}▸${Logger.C.reset} ${Logger.C.dim}${title}${Logger.C.reset} `;
55
- line += `${Logger.C.primary}[${bar}]${Logger.C.reset}`;
56
-
57
- if (showPercentage) {
58
- line += ` ${Logger.C.white}${percentage}%${Logger.C.reset}`;
59
- }
60
-
61
- if (showEta && this.current > 0) {
62
- const elapsed = Date.now() - this.startTime;
63
- const eta = Math.ceil((elapsed / this.current) * (total - this.current) / 1000);
64
- line += ` ${Logger.C.gray}(ETA: ${eta}s)${Logger.C.reset}`;
65
- }
66
-
67
- // Clear line and write new content
68
- process.stdout.write(`\r${line}`);
104
+ // Delegado para o ProgressLogger
105
+ this.logger.update(this.current);
69
106
  }
70
107
  }
71
108
 
72
- // Spinner especializado para diferentes operações
109
+ /**
110
+ * @deprecated Use ProgressLogger de src/logging/
111
+ */
73
112
  export class ThemedSpinner {
74
113
  private static frames = {
75
- default: ["", "", "", "", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
76
- dots: ["", "", "", "", "", "", "", ""],
114
+ default: ["|", "/", "-", "\\"],
115
+ dots: [".", "..", "...", "....", ".....", "....", "...", ".."],
77
116
  line: ["-", "\\", "|", "/"],
78
- arrow: ["", "", "", "", "", "", "", ""],
79
- pulse: ["", "", "", "", "", "", "", ""],
80
- moon: ["🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"]
117
+ arrow: [">", "->", "-->", "--->", "---->", "--->", "-->", "->"],
118
+ pulse: ["#", "##", "###", "####", "#####", "####", "###", "##"],
119
+ moon: ["(", "(-", "(-(", "(-(-", "(-(-(", "(-(-", "(-(", "(-"]
81
120
  };
82
121
 
83
122
  private static colors = {
84
- default: Logger.C.primary,
85
- build: Logger.C.warning,
86
- download: Logger.C.info,
87
- deploy: Logger.C.success,
88
- watch: Logger.C.secondary
123
+ default: Colors.primary,
124
+ build: Colors.warning,
125
+ download: Colors.info,
126
+ deploy: Colors.success,
127
+ watch: Colors.secondary
89
128
  };
90
129
 
91
130
  private timer?: Timer;
@@ -99,12 +138,12 @@ export class ThemedSpinner {
99
138
  const frames = ThemedSpinner.frames[theme];
100
139
  const colorCode = ThemedSpinner.colors[color];
101
140
 
102
- process.stdout.write(`${Logger.C.gray}│${Logger.C.reset} `);
141
+ process.stdout.write(`${Colors.gray}│${Colors.reset} `);
103
142
  process.stdout.write("\x1B[?25l");
104
143
 
105
144
  this.timer = setInterval(() => {
106
145
  const frame = frames[this.frameIndex];
107
- process.stdout.write(`\r${Logger.C.gray}│${Logger.C.reset} ${colorCode}${frame}${Logger.C.reset} ${Logger.C.dim}${message}${Logger.C.reset}`);
146
+ process.stdout.write(`\r${Colors.gray}│${Colors.reset} ${colorCode}${frame}${Colors.reset} ${Colors.dim}${message}${Colors.reset}`);
108
147
  this.frameIndex = (this.frameIndex + 1) % frames.length;
109
148
  }, 80);
110
149
 
@@ -114,14 +153,16 @@ export class ThemedSpinner {
114
153
  clearInterval(this.timer);
115
154
  }
116
155
  process.stdout.write("\x1B[?25h");
117
- const icon = success ? `${Logger.C.success}✓${Logger.C.reset}` : `${Logger.C.error}✗${Logger.C.reset}`;
118
- console.log(`\r${Logger.C.gray}│${Logger.C.reset} ${icon} ${message}`);
156
+ const icon = success ? `${Colors.success}✓${Colors.reset}` : `${Colors.error}✗${Colors.reset}`;
157
+ console.log(`\r${Colors.gray}│${Colors.reset} ${icon} ${message}`);
119
158
  }
120
159
  };
121
160
  }
122
161
  }
123
162
 
124
- // Função auxiliar para downloads com progresso
163
+ /**
164
+ * @deprecated Use ProgressLogger de src/logging/
165
+ */
125
166
  export async function downloadWithProgress(
126
167
  url: string,
127
168
  destination: string,
@@ -129,7 +170,7 @@ export async function downloadWithProgress(
129
170
  ): Promise<void> {
130
171
  const response = await fetch(url);
131
172
  if (!response.ok) {
132
- throw new Error(`Failed to download: ${response.statusText}`);
173
+ throw new Error(`Falha ao baixar: ${response.statusText}`);
133
174
  }
134
175
 
135
176
  const totalSize = parseInt(response.headers.get("content-length") || "0");
@@ -153,7 +194,7 @@ export async function downloadWithProgress(
153
194
 
154
195
  const reader = response.body?.getReader();
155
196
  if (!reader) {
156
- throw new Error("No response body");
197
+ throw new Error("Sem response body");
157
198
  }
158
199
 
159
200
  const chunks: Uint8Array[] = [];
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Parser de argumentos CLI com tipagem forte
3
+ * Wrapper tipado ao redor de parseArgs do Bun
4
+ */
5
+
6
+ import { parseArgs } from "util";
7
+ import type {
8
+ BaseArgs,
9
+ DeployArgs,
10
+ BuildArgs,
11
+ StartArgs,
12
+ RunArgs,
13
+ LogsArgs,
14
+ AuditArgs,
15
+ DepsArgs,
16
+ DocsArgs,
17
+ ProfilesArgs,
18
+ DoctorArgs,
19
+ TomcatCommandArgs,
20
+ EncodingCommandArgs,
21
+ ConfigArgs,
22
+ HistoryArgs,
23
+ CompletionArgs,
24
+ CleanArgs,
25
+ TestArgs,
26
+ DbArgs,
27
+ HttpArgs,
28
+ DockerArgs,
29
+ ChangelogArgs,
30
+ IdeArgs,
31
+ CLIArguments
32
+ } from "../types/args";
33
+
34
+ // Map de opções para parseArgs
35
+ const PARSE_OPTIONS = {
36
+ // Base
37
+ help: { type: "boolean", short: "h" },
38
+ version: { type: "boolean", short: "v" },
39
+ verbose: { type: "boolean", short: "V" },
40
+ quiet: { type: "boolean", short: "q" },
41
+ "debug-level": { type: "string" },
42
+
43
+ // Project
44
+ tool: { type: "string", short: "t" },
45
+ name: { type: "string", short: "n" },
46
+ profile: { type: "string", short: "P" },
47
+ encoding: { type: "string", short: "e" },
48
+ "no-build": { type: "boolean", short: "s" },
49
+ clean: { type: "boolean", short: "c" },
50
+ war: { type: "boolean", short: "W" },
51
+ cache: { type: "boolean" },
52
+
53
+ // Tomcat
54
+ path: { type: "string", short: "p" },
55
+ port: { type: "string" },
56
+ "tomcat-version": { type: "string" },
57
+ yes: { type: "boolean", short: "y" },
58
+
59
+ // Debug/Dev
60
+ debug: { type: "boolean", short: "d" },
61
+ watch: { type: "boolean", short: "w" },
62
+ tui: { type: "boolean" },
63
+ dp: { type: "string" },
64
+ incremental: { type: "boolean" },
65
+
66
+ // Analysis
67
+ grep: { type: "string", short: "G" },
68
+ scan: { type: "boolean" },
69
+ fix: { type: "boolean" },
70
+ output: { type: "string", short: "o" },
71
+ strict: { type: "boolean" },
72
+ "update-safe": { type: "boolean" },
73
+
74
+ // Encoding
75
+ from: { type: "string" },
76
+ to: { type: "string" },
77
+ backup: { type: "boolean" },
78
+ "dry-run": { type: "boolean" },
79
+ force: { type: "boolean" },
80
+ src: { type: "string" },
81
+
82
+ // Config/History
83
+ interactive: { type: "boolean", short: "i" },
84
+ clear: { type: "boolean" },
85
+ limit: { type: "string" },
86
+
87
+ // Completion
88
+ shell: { type: "string" },
89
+
90
+ // Clean
91
+ all: { type: "boolean" },
92
+ logs: { type: "boolean" },
93
+ build: { type: "boolean" },
94
+
95
+ // Test
96
+ coverage: { type: "boolean" },
97
+ "fail-fast": { type: "boolean" },
98
+ parallel: { type: "boolean" },
99
+
100
+ // HTTP
101
+ "base-url": { type: "string" },
102
+ body: { type: "string" },
103
+ file: { type: "string" },
104
+ header: { type: "string", multiple: true },
105
+ "content-type": { type: "string" },
106
+ accept: { type: "string" },
107
+ param: { type: "string", multiple: true },
108
+ timeout: { type: "string" },
109
+
110
+ // Docker
111
+ tag: { type: "string" },
112
+ "java-version": { type: "string" },
113
+ detached: { type: "boolean", short: "d" },
114
+ registry: { type: "string" },
115
+ namespace: { type: "string" },
116
+
117
+ // Multi-environment
118
+ env: { type: "string" },
119
+ environment: { type: "string" },
120
+
121
+ // Profile
122
+ profile: { type: "boolean" },
123
+
124
+ // IDE
125
+ ide: { type: "string" },
126
+ } as const;
127
+
128
+ export interface ParsedArgs<T = CLIArguments> {
129
+ values: T;
130
+ positionals: string[];
131
+ }
132
+
133
+ /**
134
+ * Parse argumentos genéricos
135
+ */
136
+ export function parseCliArgs(argv: string[]): ParsedArgs {
137
+ return parseArgs({
138
+ args: argv,
139
+ options: PARSE_OPTIONS,
140
+ strict: false,
141
+ allowPositionals: true,
142
+ }) as ParsedArgs;
143
+ }
144
+
145
+ /**
146
+ * Parse argumentos específicos para comando deploy
147
+ */
148
+ export function parseDeployArgs(argv: string[]): ParsedArgs<DeployArgs> {
149
+ const parsed = parseCliArgs(argv);
150
+ return { ...parsed, values: parsed.values as DeployArgs };
151
+ }
152
+
153
+ /**
154
+ * Parse argumentos específicos para comando build
155
+ */
156
+ export function parseBuildArgs(argv: string[]): ParsedArgs<BuildArgs> {
157
+ const parsed = parseCliArgs(argv);
158
+ return { ...parsed, values: parsed.values as BuildArgs };
159
+ }
160
+
161
+ /**
162
+ * Parse argumentos específicos para comando start
163
+ */
164
+ export function parseStartArgs(argv: string[]): ParsedArgs<StartArgs> {
165
+ const parsed = parseCliArgs(argv);
166
+ return { ...parsed, values: parsed.values as StartArgs };
167
+ }
168
+
169
+ /**
170
+ * Parse argumentos específicos para comando run/debug
171
+ */
172
+ export function parseRunArgs(argv: string[]): ParsedArgs<RunArgs> {
173
+ const parsed = parseCliArgs(argv);
174
+ return { ...parsed, values: parsed.values as RunArgs };
175
+ }
176
+
177
+ /**
178
+ * Parse argumentos específicos para comando logs
179
+ */
180
+ export function parseLogsArgs(argv: string[]): ParsedArgs<LogsArgs> {
181
+ const parsed = parseCliArgs(argv);
182
+ return { ...parsed, values: parsed.values as LogsArgs };
183
+ }
184
+
185
+ /**
186
+ * Parse argumentos específicos para comando audit
187
+ */
188
+ export function parseAuditArgs(argv: string[]): ParsedArgs<AuditArgs> {
189
+ const parsed = parseCliArgs(argv);
190
+ return { ...parsed, values: parsed.values as AuditArgs };
191
+ }
192
+
193
+ /**
194
+ * Parse argumentos específicos para comando deps
195
+ */
196
+ export function parseDepsArgs(argv: string[]): ParsedArgs<DepsArgs> {
197
+ const parsed = parseCliArgs(argv);
198
+ return { ...parsed, values: parsed.values as DepsArgs };
199
+ }
200
+
201
+ /**
202
+ * Parse argumentos específicos para comando doctor
203
+ */
204
+ export function parseDoctorArgs(argv: string[]): ParsedArgs<DoctorArgs> {
205
+ const parsed = parseCliArgs(argv);
206
+ return { ...parsed, values: parsed.values as DoctorArgs };
207
+ }
208
+
209
+ /**
210
+ * Parse argumentos específicos para comando clean
211
+ */
212
+ export function parseCleanArgs(argv: string[]): ParsedArgs<CleanArgs> {
213
+ const parsed = parseCliArgs(argv);
214
+ return { ...parsed, values: parsed.values as CleanArgs };
215
+ }
216
+
217
+ /**
218
+ * Parse argumentos específicos para comando encoding
219
+ */
220
+ export function parseEncodingArgs(argv: string[]): ParsedArgs<EncodingCommandArgs> {
221
+ const parsed = parseCliArgs(argv);
222
+ return { ...parsed, values: parsed.values as EncodingCommandArgs };
223
+ }
224
+
225
+ /**
226
+ * Obtém o comando principal dos positionals
227
+ */
228
+ export function detectCommand(positionals: string[]): string {
229
+ const commandNames = [
230
+ "deploy", "build", "start", "dev", "doctor", "run",
231
+ "debug", "logs", "docs", "audit", "profiles",
232
+ "deps", "tomcat", "encoding", "init", "config",
233
+ "history", "redo", "health", "completion", "changelog",
234
+ "test", "db", "http", "docker", "help", "clean", "ide"
235
+ ];
236
+
237
+ return positionals.find(p => commandNames.includes(p)) || "deploy";
238
+ }
239
+
240
+ /**
241
+ * Factory para parser baseado no comando
242
+ */
243
+ export function createCommandParser(command: string) {
244
+ const parsers: Record<string, (argv: string[]) => ParsedArgs> = {
245
+ deploy: parseDeployArgs,
246
+ dev: parseDeployArgs,
247
+ build: parseBuildArgs,
248
+ start: parseStartArgs,
249
+ run: parseRunArgs,
250
+ debug: parseRunArgs,
251
+ logs: parseLogsArgs,
252
+ audit: parseAuditArgs,
253
+ deps: parseDepsArgs,
254
+ doctor: parseDoctorArgs,
255
+ clean: parseCleanArgs,
256
+ encoding: parseEncodingArgs,
257
+ };
258
+
259
+ return parsers[command] || parseCliArgs;
260
+ }