@archznn/xavva 2.1.0 → 2.2.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 +3 -204
- package/package.json +1 -1
- package/src/commands/DeployCommand.ts +33 -28
- package/src/commands/DepsCommand.ts +60 -0
- package/src/commands/HelpCommand.ts +3 -0
- package/src/services/BuildService.ts +12 -4
- package/src/services/DashboardService.ts +178 -133
- package/src/services/DependencyAnalyzerService.ts +119 -11
- package/src/services/TomcatService.ts +33 -12
- package/src/utils/ui.ts +641 -312
package/src/utils/ui.ts
CHANGED
|
@@ -1,317 +1,646 @@
|
|
|
1
1
|
import pkg from "../../package.json";
|
|
2
2
|
import type { DashboardService } from "../services/DashboardService";
|
|
3
3
|
|
|
4
|
+
// Paleta de cores moderna e minimalista
|
|
5
|
+
const C = {
|
|
6
|
+
reset: "\x1b[0m",
|
|
7
|
+
bold: "\x1b[1m",
|
|
8
|
+
dim: "\x1b[2m",
|
|
9
|
+
italic: "\x1b[3m",
|
|
10
|
+
|
|
11
|
+
// Cores principais
|
|
12
|
+
primary: "\x1b[36m", // Cyan
|
|
13
|
+
primaryBright: "\x1b[96m", // Bright Cyan
|
|
14
|
+
secondary: "\x1b[35m", // Magenta
|
|
15
|
+
|
|
16
|
+
// Estados
|
|
17
|
+
success: "\x1b[32m", // Green
|
|
18
|
+
successBright: "\x1b[92m", // Bright Green
|
|
19
|
+
warning: "\x1b[33m", // Yellow
|
|
20
|
+
warningBright: "\x1b[93m", // Bright Yellow
|
|
21
|
+
error: "\x1b[31m", // Red
|
|
22
|
+
errorBright: "\x1b[91m", // Bright Red
|
|
23
|
+
info: "\x1b[34m", // Blue
|
|
24
|
+
|
|
25
|
+
// Neutros
|
|
26
|
+
white: "\x1b[37m",
|
|
27
|
+
gray: "\x1b[90m",
|
|
28
|
+
lightGray: "\x1b[37m",
|
|
29
|
+
darkGray: "\x1b[38;5;240m",
|
|
30
|
+
};
|
|
31
|
+
|
|
4
32
|
export class Logger {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
33
|
+
public static readonly C = C;
|
|
34
|
+
private static dashboard: DashboardService | null = null;
|
|
35
|
+
private static activeSpinner: { stop: (success?: boolean) => void } | null = null;
|
|
36
|
+
private static lastDomain = "";
|
|
37
|
+
|
|
38
|
+
static setDashboard(dashboard: DashboardService) {
|
|
39
|
+
this.dashboard = dashboard;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Banner completo com informações do ambiente
|
|
43
|
+
static banner(command?: string, profile?: string, encoding?: string) {
|
|
44
|
+
console.clear();
|
|
45
|
+
const git = this.getGitContext();
|
|
46
|
+
const name = process.cwd().split(/[/\\]/).pop() || "project";
|
|
47
|
+
const now = new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' });
|
|
48
|
+
const W = 52; // Largura interna do box (espaço entre os ║)
|
|
49
|
+
|
|
50
|
+
// Remove ANSI codes para calcular tamanho
|
|
51
|
+
const plain = (s: string) => s.replace(/\x1b\[\d+m/g, '');
|
|
52
|
+
|
|
53
|
+
// Cria uma linha com conteúdo alinhado à esquerda
|
|
54
|
+
const row = (content: string) => {
|
|
55
|
+
const pad = W - plain(content).length;
|
|
56
|
+
return `${C.gray}║${C.reset} ${content}${' '.repeat(Math.max(0, pad))}${C.gray}║${C.reset}`;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Linha superior
|
|
60
|
+
console.log(`${C.gray}╔══════════════════════════════════════════════════════╗${C.reset}`);
|
|
61
|
+
|
|
62
|
+
// Linha 1: XAVVA v2.2.0 + hora alinhada à direita
|
|
63
|
+
const verPlain = `XAVVA v${pkg.version}`; // "XAVVA v2.2.0" = 12 chars
|
|
64
|
+
const timePlain = now; // 5 chars
|
|
65
|
+
const gap1 = W - verPlain.length - timePlain.length - 1; // -1 para deixar 1 espaço antes do ║
|
|
66
|
+
const line1Content = `${C.primary}${C.bold}XAVVA${C.reset}${C.gray} v${pkg.version}${C.reset}${' '.repeat(Math.max(1, gap1))}${C.dim}${now}${C.reset}`;
|
|
67
|
+
console.log(row(line1Content));
|
|
68
|
+
|
|
69
|
+
// Linha 2: Nome do projeto
|
|
70
|
+
console.log(row(`${C.white}${C.bold}${name}${C.reset}`));
|
|
71
|
+
|
|
72
|
+
// Linha 3: Git info
|
|
73
|
+
if (git.branch) {
|
|
74
|
+
const gitStatus = this.getGitStatus();
|
|
75
|
+
const dirty = gitStatus.dirty ? '*' : '';
|
|
76
|
+
const author = git.author ? git.author.split(' ')[0].slice(0, 10) : '';
|
|
77
|
+
const hash = git.hash ? git.hash.slice(0, 7) : '';
|
|
78
|
+
const branchDisplay = git.branch.slice(0, 20); // Limita branch
|
|
79
|
+
const gitLine = `${C.gray}git:${C.reset}${C.secondary}${branchDisplay}${dirty}${C.reset} ${C.dim}${hash}${C.reset} ${C.gray}by${C.reset} ${C.dim}${author}${C.reset}`;
|
|
80
|
+
console.log(row(gitLine));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Divisor
|
|
84
|
+
console.log(`${C.gray}╠══════════════════════════════════════════════════════╣${C.reset}`);
|
|
85
|
+
|
|
86
|
+
// Config: mode, profile, java, encoding
|
|
87
|
+
const cfg: string[] = [];
|
|
88
|
+
if (command) cfg.push(`${C.primary}${command}${C.reset}`);
|
|
89
|
+
if (profile) cfg.push(`${C.warning}${profile}${C.reset}`);
|
|
90
|
+
const jv = this.getJavaVersion();
|
|
91
|
+
if (jv) cfg.push(`${C.info}java:${jv}${C.reset}`);
|
|
92
|
+
if (encoding) cfg.push(`${C.gray}${encoding}${C.reset}`);
|
|
93
|
+
|
|
94
|
+
if (cfg.length) {
|
|
95
|
+
const sep = `${C.gray} │ ${C.reset}`;
|
|
96
|
+
const cfgLine = `${C.dim}mode${C.reset} : ${cfg.join(sep)}`;
|
|
97
|
+
console.log(row(cfgLine));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Memory
|
|
101
|
+
const mem = process.memoryUsage();
|
|
102
|
+
const mb = Math.round((mem.heapUsed || mem.rss || 0) / 1024 / 1024);
|
|
103
|
+
console.log(row(`${C.dim}mem${C.reset} : ${mb}MB ${C.gray}heap${C.reset}`));
|
|
104
|
+
|
|
105
|
+
// OS
|
|
106
|
+
const plat = process.platform === 'win32' ? 'windows' : process.platform;
|
|
107
|
+
console.log(row(`${C.dim}os${C.reset} : ${plat} ${C.gray}|${C.reset} ${process.arch}`));
|
|
108
|
+
|
|
109
|
+
// Rodapé
|
|
110
|
+
console.log(`${C.gray}╚══════════════════════════════════════════════════════╝${C.reset}`);
|
|
111
|
+
console.log();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private static getGitStatus(): { dirty: boolean; modified: number } {
|
|
115
|
+
try {
|
|
116
|
+
const result = Bun.spawnSync(["git", "status", "--porcelain"]);
|
|
117
|
+
const lines = result.stdout.toString().trim().split('\n').filter(l => l.trim());
|
|
118
|
+
return { dirty: lines.length > 0, modified: lines.length };
|
|
119
|
+
} catch {
|
|
120
|
+
return { dirty: false, modified: 0 };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private static getJavaVersion(): string | null {
|
|
125
|
+
try {
|
|
126
|
+
const javaBin = process.env.JAVA_HOME
|
|
127
|
+
? `${process.env.JAVA_HOME}/bin/java`
|
|
128
|
+
: 'java';
|
|
129
|
+
const result = Bun.spawnSync([javaBin, "-version"]);
|
|
130
|
+
const output = (result.stderr?.toString() || result.stdout?.toString() || '');
|
|
131
|
+
const match = output.match(/version "?(\d+(?:\.\d+)?)/);
|
|
132
|
+
if (match) {
|
|
133
|
+
const v = match[1];
|
|
134
|
+
// Check for DCEVM
|
|
135
|
+
if (output.toLowerCase().includes('dcevm') || output.toLowerCase().includes('jbr')) {
|
|
136
|
+
return `${v}+dcevm`;
|
|
137
|
+
}
|
|
138
|
+
return v;
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
} catch {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Seções com divisórias clean
|
|
147
|
+
static section(title: string) {
|
|
148
|
+
console.log(`${C.gray}┌─ ${C.white}${C.bold}${title}${C.reset}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static endSection() {
|
|
152
|
+
console.log(`${C.gray}└${C.reset}`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Configurações em formato chave: valor alinhado
|
|
156
|
+
static config(label: string, value: string | number | boolean) {
|
|
157
|
+
const valueStr = String(value);
|
|
158
|
+
const isBool = typeof value === 'boolean';
|
|
159
|
+
const displayValue = isBool
|
|
160
|
+
? (value ? `${C.successBright}✓${C.reset} ${C.success}enabled${C.reset}` : `${C.gray}○${C.reset} ${C.gray}disabled${C.reset}`)
|
|
161
|
+
: `${C.white}${valueStr}${C.reset}`;
|
|
162
|
+
|
|
163
|
+
console.log(`${C.gray}│${C.reset} ${C.dim}${label.padEnd(12)}${C.reset} ${C.gray}:${C.reset} ${displayValue}`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Status com ícones minimalistas
|
|
167
|
+
static ready(msg: string) {
|
|
168
|
+
console.log(`${C.gray}│${C.reset} ${C.success}●${C.reset} ${msg}`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
static info(label: string, value?: string) {
|
|
172
|
+
if (value) {
|
|
173
|
+
console.log(`${C.gray}│${C.reset} ${C.dim}${label}${C.reset} ${C.gray}:${C.reset} ${C.white}${value}${C.reset}`);
|
|
174
|
+
} else {
|
|
175
|
+
console.log(`${C.gray}│${C.reset} ${C.info}ℹ${C.reset} ${label}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
static success(msg: string) {
|
|
180
|
+
console.log(`${C.gray}│${C.reset} ${C.success}✓${C.reset} ${msg}`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
static error(msg: string) {
|
|
184
|
+
console.log(`${C.gray}│${C.reset} ${C.error}✗${C.reset} ${C.error}${msg}${C.reset}`);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
static warn(msg: string) {
|
|
188
|
+
console.log(`${C.gray}│${C.reset} ${C.warning}⚠${C.reset} ${msg}`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
static debug(msg: string) {
|
|
192
|
+
console.log(`${C.gray}│${C.reset} ${C.gray}🐛 ${msg}${C.reset}`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
static step(msg: string) {
|
|
196
|
+
console.log(`${C.gray}│${C.reset} ${C.gray}▸ ${msg}${C.reset}`);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
static log(msg: string) {
|
|
200
|
+
console.log(msg);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
static dim(msg: string) {
|
|
204
|
+
console.log(`${C.dim}${msg}${C.reset}`);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
static newline() {
|
|
208
|
+
console.log();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
static watcher(msg: string, _type?: string) {
|
|
212
|
+
console.log(`${C.gray}│${C.reset} ${C.secondary}◉${C.reset} ${C.dim}watch${C.reset} ${C.gray}:${C.reset} ${msg}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
static watch(msg: string) {
|
|
216
|
+
console.log(`${C.gray}│${C.reset} ${C.secondary}◉${C.reset} ${C.dim}watch${C.reset} ${C.gray}:${C.reset} ${msg}`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
static process(msg: string) {
|
|
220
|
+
console.log(`${C.gray}│${C.reset} ${C.primary}▸${C.reset} ${C.dim}process${C.reset} ${C.gray}:${C.reset} ${msg}`);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
static build(msg: string) {
|
|
224
|
+
console.log(`${C.gray}│${C.reset} ${C.primary}▸${C.reset} ${C.dim}build${C.reset} ${C.gray}:${C.reset} ${msg}`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
static server(msg: string) {
|
|
228
|
+
console.log(`${C.gray}│${C.reset} ${C.primary}▸${C.reset} ${C.dim}server${C.reset} ${C.gray}:${C.reset} ${msg}`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
static hotswap(msg: string) {
|
|
232
|
+
console.log(`${C.gray}│${C.reset} ${C.secondary}↻${C.reset} ${C.dim}hotswap${C.reset} ${C.gray}:${C.reset} ${msg}`);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// URL formatada de forma destacada
|
|
236
|
+
static url(label: string, url: string) {
|
|
237
|
+
console.log(`${C.gray}│${C.reset} ${C.dim}${label}${C.reset} ${C.gray}:${C.reset} ${C.primaryBright}${C.bold}${url}${C.reset}`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Spinner moderno
|
|
241
|
+
static spinner(msg: string) {
|
|
242
|
+
if (this.dashboard?.isTuiActive()) {
|
|
243
|
+
return this.dashboard.spinner(msg);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
247
|
+
let i = 0;
|
|
248
|
+
|
|
249
|
+
process.stdout.write(`${C.gray}│${C.reset} `);
|
|
250
|
+
process.stdout.write("\x1B[?25l");
|
|
251
|
+
|
|
252
|
+
const timer = setInterval(() => {
|
|
253
|
+
process.stdout.write(`\r${C.gray}│${C.reset} ${C.primary}${frames[i]}${C.reset} ${C.dim}${msg}${C.reset}`);
|
|
254
|
+
i = (i + 1) % frames.length;
|
|
255
|
+
}, 80);
|
|
256
|
+
|
|
257
|
+
return (success = true) => {
|
|
258
|
+
clearInterval(timer);
|
|
259
|
+
process.stdout.write("\x1B[?25h");
|
|
260
|
+
if (success) {
|
|
261
|
+
console.log(`\r${C.gray}│${C.reset} ${C.success}✓${C.reset} ${msg}`);
|
|
262
|
+
} else {
|
|
263
|
+
console.log(`\r${C.gray}│${C.reset} ${C.error}✗${C.reset} ${C.error}${msg}${C.reset}`);
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Divisória simples
|
|
269
|
+
static divider() {
|
|
270
|
+
console.log(`${C.gray}├────────────────────────────────────────────────────────┤${C.reset}`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Finalização
|
|
274
|
+
static done() {
|
|
275
|
+
console.log(`${C.gray}└────────────────────────────────────────────────────────┘${C.reset}`);
|
|
276
|
+
console.log();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Helper para contexto git
|
|
280
|
+
static getGitContext(): { branch: string; author: string; hash: string } {
|
|
281
|
+
try {
|
|
282
|
+
const branch = Bun.spawnSync(["git", "rev-parse", "--abbrev-ref", "HEAD"]).stdout.toString().trim();
|
|
283
|
+
const author = Bun.spawnSync(["git", "log", "-1", "--format=%an"]).stdout.toString().trim();
|
|
284
|
+
const hash = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"]).stdout.toString().trim();
|
|
285
|
+
return { branch, author, hash };
|
|
286
|
+
} catch {
|
|
287
|
+
return { branch: "", author: "", hash: "" };
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Filtros de noise (mantidos)
|
|
292
|
+
// Controle de rate limiting para hotswap
|
|
293
|
+
private static lastHotswapTime = 0;
|
|
294
|
+
private static hotswapCount = 0;
|
|
295
|
+
|
|
296
|
+
static isSystemNoise(line: string): boolean {
|
|
297
|
+
const noise = [
|
|
298
|
+
"Using CATALINA_", "Using JRE_HOME", "Using CLASSPATH",
|
|
299
|
+
"Scanning for projects...", "Building ", "--- ", "+++ ",
|
|
300
|
+
"Arquivos processados em", "milliseconds",
|
|
301
|
+
"SLF4J: ", "Discovered plugins:",
|
|
302
|
+
"enhanced with plugin initialization", "Hotswap ready",
|
|
303
|
+
"autoHotswap.delay", "watchResources=false",
|
|
304
|
+
// HotswapAgent noise
|
|
305
|
+
"TreeWatcherNIO", "HOTSWAP AGENT", "org.hotswap.agent",
|
|
306
|
+
// Jersey/JAX-RS noise
|
|
307
|
+
"org.glassfish.jersey", "The (sub)resource method",
|
|
308
|
+
// Tomcat noise
|
|
309
|
+
"org.apache.catalina", "org.apache.jasper",
|
|
310
|
+
];
|
|
311
|
+
return noise.some(n => line.includes(n));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
static isEssential(line: string): boolean {
|
|
315
|
+
return line.includes("SEVERE") || line.includes("ERROR") || line.includes("Exception") ||
|
|
316
|
+
line.includes("Caused by") || line.includes("at ") || line.includes("... ") ||
|
|
317
|
+
line.includes("Server startup in") || line.includes("HOTSWAP AGENT:");
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Sumarização de logs do Tomcat (simplificada)
|
|
321
|
+
static summarize(line: string): string {
|
|
322
|
+
if (this.isSystemNoise(line)) return "";
|
|
323
|
+
|
|
324
|
+
// Server startup
|
|
325
|
+
const startupMatch = line.match(/Server startup in.*?([\d,]+)\s*ms/);
|
|
326
|
+
if (startupMatch) {
|
|
327
|
+
const time = startupMatch[1].replace(",", "");
|
|
328
|
+
const seconds = (parseInt(time) / 1000).toFixed(1);
|
|
329
|
+
return `${C.success}ready ${C.gray}in ${C.white}${seconds}s${C.reset}`;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Hotswap com rate limiting (evita spam)
|
|
333
|
+
if (line.includes("HOTSWAP AGENT") && line.includes("RELOAD")) {
|
|
334
|
+
const now = Date.now();
|
|
335
|
+
if (now - this.lastHotswapTime < 2000) {
|
|
336
|
+
this.hotswapCount++;
|
|
337
|
+
return ""; // Silencia se dentro de 2s
|
|
338
|
+
}
|
|
339
|
+
this.lastHotswapTime = now;
|
|
340
|
+
const count = this.hotswapCount > 0 ? ` ${C.gray}(${this.hotswapCount} more)${C.reset}` : "";
|
|
341
|
+
this.hotswapCount = 0;
|
|
342
|
+
return `${C.secondary}↻ hotswap${C.reset}${count}`;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Erros de compilação
|
|
346
|
+
const compilationError = line.match(/\[ERROR\].*?(\w+\.java):\[(\d+).*?\]\s*(.+)/);
|
|
347
|
+
if (compilationError) {
|
|
348
|
+
const [, file, lineNum, msg] = compilationError;
|
|
349
|
+
return `${C.error}✗ ${C.white}${file}${C.gray}:${lineNum}${C.reset} ${C.gray}${msg.slice(0, 50)}${C.reset}`;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Erros SEVERE
|
|
353
|
+
if (line.includes("SEVERE") || line.includes("Exception")) {
|
|
354
|
+
return `${C.error}✗ ${C.gray}${line.slice(0, 80)}${C.reset}`;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Warnings (filtra noise conhecido)
|
|
358
|
+
if (line.includes("WARNING") || line.includes("ADVERTÊNCIA")) {
|
|
359
|
+
if (this.isSystemNoise(line)) return "";
|
|
360
|
+
return `${C.warning}⚠ ${C.gray}${line.slice(0, 80)}${C.reset}`;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return "";
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// ========== Tomcat Log Formatting ==========
|
|
367
|
+
|
|
368
|
+
private static tomcatNoisePatterns = [
|
|
369
|
+
/^Using CATALINA_/,
|
|
370
|
+
/^Using JRE_HOME/,
|
|
371
|
+
/^Using CLASSPATH/,
|
|
372
|
+
/^Using CATALINA_OPTS/,
|
|
373
|
+
/^NOTE: Picked up JDK_JAVA_OPTIONS/,
|
|
374
|
+
/^HOTSWAP AGENT:.*Plugin.*initialized in ClassLoader/,
|
|
375
|
+
/^HOTSWAP AGENT:.*Registering directory/,
|
|
376
|
+
/^HOTSWAP AGENT:.*WARNING.*TreeWatcherNIO.*Unable to watch/,
|
|
377
|
+
/^HOTSWAP AGENT:.*INFO.*TreeWatcherNIO/,
|
|
378
|
+
/^HOTSWAP AGENT:.*INFO.*PluginRegistry.*Discovered plugins/,
|
|
379
|
+
/^HOTSWAP AGENT:.*INFO.*HotswapAgent.*Loading Hotswap agent/,
|
|
380
|
+
/^HOTSWAP AGENT:.*INFO.*TomcatPlugin.*Tomcat plugin initialized/,
|
|
381
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*VersionLoggerListener/,
|
|
382
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*AprLifecycleListener/,
|
|
383
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*Command line argument/,
|
|
384
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*CATALINA_BASE/,
|
|
385
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*CATALINA_HOME/,
|
|
386
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*Server version/,
|
|
387
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*Server built/,
|
|
388
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*OS Name/,
|
|
389
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*OS Version/,
|
|
390
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*Architecture/,
|
|
391
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*Java Home/,
|
|
392
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*JVM Version/,
|
|
393
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*JVM Vendor/,
|
|
394
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*Loaded Apache Tomcat Native/,
|
|
395
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*APR capabilities/,
|
|
396
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*APR\/OpenSSL configuration/,
|
|
397
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*OpenSSL successfully initialized/,
|
|
398
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*Server initialization in/,
|
|
399
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*Starting service/,
|
|
400
|
+
/^\d{2}-[A-Za-z]+-\d{4}\s+\d{2}:\d{2}:\d{2}\.\d+\s+(INFORMAÇÕES|INFO)\s+\[main\].*Starting Servlet engine/,
|
|
401
|
+
/^ParallelWebappClassLoader/,
|
|
402
|
+
/^context:/,
|
|
403
|
+
/^delegate:/,
|
|
404
|
+
/^-+> Parent Classloader/,
|
|
405
|
+
/^java\.net\.URLClassLoader/,
|
|
406
|
+
];
|
|
407
|
+
|
|
408
|
+
static isTomcatNoise(line: string): boolean {
|
|
409
|
+
return this.tomcatNoisePatterns.some(p => p.test(line));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
static formatTomcatLog(line: string): string {
|
|
413
|
+
const cleanLine = line.trim();
|
|
414
|
+
if (!cleanLine) return "";
|
|
415
|
+
|
|
416
|
+
// Silencia noise completamente
|
|
417
|
+
if (this.isTomcatNoise(cleanLine)) return "";
|
|
418
|
+
|
|
419
|
+
// HOTSWAP AGENT: Loading Hotswap agent X.X.X
|
|
420
|
+
if (cleanLine.includes("HOTSWAP AGENT") && cleanLine.includes("Loading Hotswap agent")) {
|
|
421
|
+
const versionMatch = cleanLine.match(/Loading Hotswap agent ([\d.]+)/);
|
|
422
|
+
if (versionMatch) {
|
|
423
|
+
return `${C.gray}│${C.reset} ${C.secondary}↻${C.reset} ${C.dim}HotswapAgent v${versionMatch[1]}${C.reset}`;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// HOTSWAP AGENT: Discovered plugins
|
|
428
|
+
if (cleanLine.includes("HOTSWAP AGENT") && cleanLine.includes("Discovered plugins")) {
|
|
429
|
+
return `${C.gray}│${C.reset} ${C.secondary}↻${C.reset} ${C.dim}plugins loaded${C.reset}`;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Server initialization
|
|
433
|
+
const initMatch = cleanLine.match(/Server initialization in \[(\d+)\] milliseconds/);
|
|
434
|
+
if (initMatch) {
|
|
435
|
+
return `${C.gray}│${C.reset} ${C.success}●${C.reset} ${C.dim}initialized in ${initMatch[1]}ms${C.reset}`;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Starting service [Catalina]
|
|
439
|
+
const serviceMatch = cleanLine.match(/Starting service \[(\w+)\]/);
|
|
440
|
+
if (serviceMatch) {
|
|
441
|
+
return `${C.gray}│${C.reset} ${C.primary}▸${C.reset} ${C.dim}starting ${serviceMatch[1].toLowerCase()}${C.reset}`;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Starting Servlet engine
|
|
445
|
+
if (cleanLine.includes("Starting Servlet engine")) {
|
|
446
|
+
const versionMatch = cleanLine.match(/Apache Tomcat\/([\d.]+)/);
|
|
447
|
+
if (versionMatch) {
|
|
448
|
+
return `${C.gray}│${C.reset} ${C.primary}▸${C.reset} ${C.dim}Tomcat ${versionMatch[1]}${C.reset}`;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Deploy directory
|
|
453
|
+
const deployMatch = cleanLine.match(/deployDirectory.*webapps[\\/]([^'"\]]+)/);
|
|
454
|
+
if (deployMatch) {
|
|
455
|
+
return `${C.gray}│${C.reset} ${C.primary}▸${C.reset} ${C.dim}deploying ${deployMatch[1]}${C.reset}`;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Server startup in ( já temos no summarize mas reforça aqui )
|
|
459
|
+
const startupMatch = cleanLine.match(/Server startup in.*?([\d,]+)\s*ms/);
|
|
460
|
+
if (startupMatch) {
|
|
461
|
+
const time = startupMatch[1].replace(",", "");
|
|
462
|
+
const seconds = (parseInt(time) / 1000).toFixed(1);
|
|
463
|
+
return `${C.gray}│${C.reset} ${C.success}●${C.reset} ${C.dim}ready in ${C.white}${seconds}s${C.reset}`;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Tomcat versão info (sumarizado)
|
|
467
|
+
const tomcatVersionMatch = cleanLine.match(/Server version number:\s+([\d.]+)/);
|
|
468
|
+
if (tomcatVersionMatch) {
|
|
469
|
+
return `${C.gray}│${C.reset} ${C.dim}Tomcat ${tomcatVersionMatch[1]}${C.reset}`;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// JVM info sumarizada
|
|
473
|
+
const jvmMatch = cleanLine.match(/JVM Version:\s+([\d._]+)/);
|
|
474
|
+
if (jvmMatch) {
|
|
475
|
+
return `${C.gray}│${C.reset} ${C.dim}JVM ${jvmMatch[1]}${C.reset}`;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Protocol handler init
|
|
479
|
+
const protocolMatch = cleanLine.match(/Initializing ProtocolHandler \["(.+?)"\]/);
|
|
480
|
+
if (protocolMatch) {
|
|
481
|
+
return `${C.gray}│${C.reset} ${C.primary}▸${C.reset} ${C.dim}${protocolMatch[1]}${C.reset}`;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Erros e warnings que passaram pelo filtro
|
|
485
|
+
if (cleanLine.includes("SEVERE") || cleanLine.includes("ERROR")) {
|
|
486
|
+
return `${C.gray}│${C.reset} ${C.error}✗${C.reset} ${C.gray}${cleanLine.slice(0, 80)}${C.reset}`;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (cleanLine.includes("WARNING") || cleanLine.includes("ADVERTÊNCIA")) {
|
|
490
|
+
return `${C.gray}│${C.reset} ${C.warning}⚠${C.reset} ${C.gray}${cleanLine.slice(0, 80)}${C.reset}`;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// Outros logs INFO - mostra resumido
|
|
494
|
+
const infoMatch = cleanLine.match(/(?:INFORMAÇÕES|INFO)\s+\[.*?\]\s+(.+)/);
|
|
495
|
+
if (infoMatch) {
|
|
496
|
+
const msg = infoMatch[1].trim();
|
|
497
|
+
if (msg.length > 0 && !this.isTomcatNoise(msg)) {
|
|
498
|
+
return `${C.gray}│${C.reset} ${C.dim}${msg.slice(0, 70)}${C.reset}`;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
return "";
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// ========== Build Log Formatting (Maven/Gradle) ==========
|
|
506
|
+
|
|
507
|
+
private static buildNoisePatterns = [
|
|
508
|
+
/^\[INFO\]\s+Scanning for projects/,
|
|
509
|
+
/^\[INFO\]\s+Using the MultiThreadedBuilder/,
|
|
510
|
+
/^\[INFO\]\s+---\s+.*\s+---$/,
|
|
511
|
+
/^\[INFO\]\s+T+E+\s*$/,
|
|
512
|
+
/^\[INFO\]\s+BUILD\s+SUCCESS/i,
|
|
513
|
+
/^\[INFO\]\s+BUILD\s+FAILURE/i,
|
|
514
|
+
/^\[INFO\]\s+Total time:/,
|
|
515
|
+
/^\[INFO\]\s+Finished at:/,
|
|
516
|
+
/^\[INFO\]\s+Final Memory:/,
|
|
517
|
+
/^\[INFO\]\s+http:\/\/cwiki\.apache\.org/,
|
|
518
|
+
/^\[INFO\]\s+-> \[Help 1\]/,
|
|
519
|
+
/^\[INFO\]\s+Re-run Maven using/,
|
|
520
|
+
/^\[INFO\]\s+To see the full stack trace/,
|
|
521
|
+
/^\[INFO\]\s+For more information about the errors/,
|
|
522
|
+
/^\[ERROR\]\s+To see the full stack trace/,
|
|
523
|
+
/^\[ERROR\]\s+Re-run Maven using/,
|
|
524
|
+
/^\[ERROR\]\s+For more information/,
|
|
525
|
+
/^\[ERROR\]\s+-> \[Help 1\]/,
|
|
526
|
+
/^\[WARNING\]\s+It is highly recommended/,
|
|
527
|
+
/^\[WARNING\]\s+For this reason, future Maven/,
|
|
528
|
+
/^\[WARNING\]\s+\[HELP, sysprop:version/,
|
|
529
|
+
/^\[WARNING\]\s+Some problems were encountered/,
|
|
530
|
+
/^\[WARNING\]\s+'dependencies\.dependency/,
|
|
531
|
+
/Building .*war/,
|
|
532
|
+
/from pom\.xml/,
|
|
533
|
+
/\[ war \]/,
|
|
534
|
+
/^\s*$/,
|
|
535
|
+
];
|
|
536
|
+
|
|
537
|
+
private static gradleNoisePatterns = [
|
|
538
|
+
/^> Task/,
|
|
539
|
+
/^Download/,
|
|
540
|
+
/^Expiring/,
|
|
541
|
+
/^BUILD/,
|
|
542
|
+
/^\d+ actionable task/,
|
|
543
|
+
];
|
|
544
|
+
|
|
545
|
+
static isBuildNoise(line: string): boolean {
|
|
546
|
+
return this.buildNoisePatterns.some(p => p.test(line)) ||
|
|
547
|
+
this.gradleNoisePatterns.some(p => p.test(line));
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Acumulador de erro de compilação (para pegar mensagens multi-linha)
|
|
551
|
+
private static pendingError: { file: string; line: string; msg: string } | null = null;
|
|
552
|
+
|
|
553
|
+
static formatBuildLog(line: string, buildTool: 'maven' | 'gradle' = 'maven'): string {
|
|
554
|
+
const cleanLine = line.trim();
|
|
555
|
+
if (!cleanLine) return "";
|
|
556
|
+
|
|
557
|
+
// Maven: [ERROR] /path/file.java:[123,45] error message
|
|
558
|
+
const mavenErrorMatch = cleanLine.match(/^\[ERROR\]\s+(.+\.java):\[(\d+),\d+\]\s*(.+)/);
|
|
559
|
+
if (mavenErrorMatch) {
|
|
560
|
+
const [, file, lineNum, msg] = mavenErrorMatch;
|
|
561
|
+
const shortFile = file.split(/[/\\]/).pop() || file;
|
|
562
|
+
return `${C.gray}│${C.reset} ${C.error}✗${C.reset} ${C.white}${shortFile}${C.gray}:${lineNum}${C.reset} ${C.error}${msg.slice(0, 60)}${C.reset}`;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Maven: [ERROR] COMPILATION ERROR / BUILD FAILURE (título)
|
|
566
|
+
if (cleanLine.match(/^\[(ERROR|INFO)\]\s+(COMPILATION ERROR|BUILD FAILURE)/)) {
|
|
567
|
+
return `${C.gray}│${C.reset} ${C.error}✗ COMPILATION FAILED${C.reset}`;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Maven: [WARNING] 'dependencies.dependency...'
|
|
571
|
+
if (cleanLine.match(/^\[WARNING\]\s+'dependencies\.dependency/)) {
|
|
572
|
+
const match = cleanLine.match(/'dependencies\.dependency\.[\w:]+'\s+(.+)/);
|
|
573
|
+
if (match) {
|
|
574
|
+
return `${C.gray}│${C.reset} ${C.warning}⚠${C.reset} ${C.gray}${match[1].slice(0, 60)}${C.reset}`;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// Maven: [WARNING] The POM for ... is invalid
|
|
579
|
+
const invalidPomMatch = cleanLine.match(/^\[WARNING\]\s+The POM for (.+?) is invalid/);
|
|
580
|
+
if (invalidPomMatch) {
|
|
581
|
+
return `${C.gray}│${C.reset} ${C.warning}⚠${C.reset} ${C.gray}Invalid POM: ${invalidPomMatch[1].slice(0, 50)}${C.reset}`;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// Maven: [INFO] Compiling N source files
|
|
585
|
+
const compilingMatch = cleanLine.match(/^\[INFO\]\s+Compiling\s+(\d+)\s+source/);
|
|
586
|
+
if (compilingMatch) {
|
|
587
|
+
return `${C.gray}│${C.reset} ${C.primary}▸${C.reset} ${C.dim}compiling ${C.white}${compilingMatch[1]}${C.reset} ${C.dim}files${C.reset}`;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// Maven: [INFO] /path/file.java: Some input files use or override a deprecated API
|
|
591
|
+
const deprecatedMatch = cleanLine.match(/^\[INFO\]\s+(.+\.java):\s+Some input files use (.+)/);
|
|
592
|
+
if (deprecatedMatch) {
|
|
593
|
+
const shortFile = deprecatedMatch[1].split(/[/\\]/).pop() || deprecatedMatch[1];
|
|
594
|
+
const type = deprecatedMatch[2].includes('removal') ? 'deprecated (removal)' : 'deprecated';
|
|
595
|
+
return `${C.gray}│${C.reset} ${C.warning}⚠${C.reset} ${C.gray}${shortFile} uses ${type}${C.reset}`;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Maven: [INFO] Changes detected - recompiling
|
|
599
|
+
if (cleanLine.match(/^\[INFO\]\s+Changes detected/)) {
|
|
600
|
+
return `${C.gray}│${C.reset} ${C.primary}▸${C.reset} ${C.dim}changes detected, recompiling${C.reset}`;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Maven: [INFO] Copying N resources
|
|
604
|
+
const resourcesMatch = cleanLine.match(/^\[INFO\]\s+Copying\s+(\d+)\s+resources?/);
|
|
605
|
+
if (resourcesMatch) {
|
|
606
|
+
return `${C.gray}│${C.reset} ${C.dim}copying ${C.white}${resourcesMatch[1]}${C.reset} ${C.dim}resources${C.reset}`;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// Maven: [INFO] Deleting ...
|
|
610
|
+
const deletingMatch = cleanLine.match(/^\[INFO\]\s+Deleting\s+(.+)/);
|
|
611
|
+
if (deletingMatch) {
|
|
612
|
+
return `${C.gray}│${C.reset} ${C.dim}cleaning target directory${C.reset}`;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// Maven: [INFO] skip non existing resourceDirectory
|
|
616
|
+
if (cleanLine.match(/^\[INFO\]\s+skip non existing/)) {
|
|
617
|
+
return ""; // Silencia
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// Gradle: > Task :name
|
|
621
|
+
const gradleTaskMatch = cleanLine.match(/^> Task :(.+)/);
|
|
622
|
+
if (gradleTaskMatch) {
|
|
623
|
+
return `${C.gray}│${C.reset} ${C.primary}▸${C.reset} ${C.dim}${gradleTaskMatch[1]}${C.reset}`;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// Gradle errors
|
|
627
|
+
const gradleErrorMatch = cleanLine.match(/^(.+\.java):(\d+):\s*(error|warning):\s*(.+)/);
|
|
628
|
+
if (gradleErrorMatch) {
|
|
629
|
+
const [, file, lineNum, level, msg] = gradleErrorMatch;
|
|
630
|
+
const shortFile = file.split(/[/\\]/).pop() || file;
|
|
631
|
+
const icon = level === 'error' ? C.error + '✗' + C.reset : C.warning + '⚠' + C.reset;
|
|
632
|
+
return `${C.gray}│${C.reset} ${icon} ${C.white}${shortFile}${C.gray}:${lineNum}${C.reset} ${C.error}${msg.slice(0, 60)}${C.reset}`;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// Se não for nenhum padrão conhecido e não for noise, retorna formatado como info
|
|
636
|
+
if (!this.isBuildNoise(cleanLine)) {
|
|
637
|
+
// Remove prefixos [INFO], [WARNING], [ERROR] genéricos
|
|
638
|
+
const clean = cleanLine.replace(/^\[(INFO|WARNING|ERROR)\]\s*/, '');
|
|
639
|
+
if (clean.length > 0 && !this.isBuildNoise(clean)) {
|
|
640
|
+
return `${C.gray}│${C.reset} ${C.dim}${clean.slice(0, 70)}${C.reset}`;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
return "";
|
|
645
|
+
}
|
|
317
646
|
}
|