@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.
- package/README.md +221 -12
- package/package.json +3 -2
- package/src/commands/AuditCommand.ts +12 -10
- package/src/commands/BuildCommand.ts +9 -7
- package/src/commands/ChangelogCommand.ts +5 -5
- package/src/commands/CleanCommand.ts +242 -0
- package/src/commands/CompletionCommand.ts +7 -7
- package/src/commands/DbCommand.ts +33 -31
- package/src/commands/DeployCommand.ts +252 -229
- package/src/commands/DepsCommand.ts +174 -174
- package/src/commands/DockerCommand.ts +14 -14
- package/src/commands/DoctorCommand.ts +252 -239
- package/src/commands/EncodingCommand.ts +19 -19
- package/src/commands/HealthCommand.ts +7 -7
- package/src/commands/HelpCommand.ts +34 -14
- package/src/commands/HistoryCommand.ts +5 -5
- package/src/commands/HttpCommand.ts +6 -6
- package/src/commands/IdeCommand.ts +313 -0
- package/src/commands/InitCommand.ts +26 -25
- package/src/commands/LogsCommand.ts +8 -6
- package/src/commands/ProfilesCommand.ts +6 -6
- package/src/commands/RedoCommand.ts +2 -2
- package/src/commands/RunCommand.ts +64 -24
- package/src/commands/StartCommand.ts +9 -7
- package/src/commands/TestCommand.ts +4 -4
- package/src/commands/TomcatCommand.ts +219 -100
- package/src/config/versions.ts +111 -9
- package/src/di/container.ts +239 -105
- package/src/errors/ErrorHandler.ts +23 -19
- package/src/errors/errorMessages.ts +235 -0
- package/src/index.ts +11 -3
- package/src/logging/FileLogger.ts +235 -0
- package/src/logging/Logger.ts +545 -0
- package/src/logging/OperationLogger.ts +296 -0
- package/src/logging/ProgressLogger.ts +187 -0
- package/src/logging/TableLogger.ts +246 -0
- package/src/logging/colors.ts +167 -0
- package/src/logging/constants.ts +176 -0
- package/src/logging/formatters.ts +337 -0
- package/src/logging/index.ts +93 -0
- package/src/logging/types.ts +64 -0
- package/src/plugins/PluginManager.ts +325 -0
- package/src/plugins/types.ts +82 -0
- package/src/services/AuditService.ts +5 -3
- package/src/services/BuildService.ts +15 -17
- package/src/services/DashboardService.ts +14 -3
- package/src/services/DbService.ts +35 -34
- package/src/services/DependencyAnalyzerService.ts +18 -18
- package/src/services/DependencyCacheService.ts +303 -0
- package/src/services/DeployWatcher.ts +127 -23
- package/src/services/DockerService.ts +3 -3
- package/src/services/EmbeddedTomcatService.ts +13 -12
- package/src/services/FileWatcher.ts +15 -7
- package/src/services/HttpService.ts +5 -5
- package/src/services/LogAnalyzer.ts +26 -22
- package/src/services/PerformanceProfiler.ts +267 -0
- package/src/services/ProjectService.ts +3 -0
- package/src/services/TestService.ts +3 -3
- package/src/services/TomcatService.ts +46 -25
- package/src/services/tomcat/TomcatBackupManager.ts +330 -0
- package/src/services/tomcat/TomcatChecksumVerifier.ts +211 -0
- package/src/services/tomcat/TomcatCompatibilityChecker.ts +298 -0
- package/src/services/tomcat/TomcatDownloadCache.ts +250 -0
- package/src/services/tomcat/TomcatDownloadService.ts +335 -0
- package/src/services/tomcat/TomcatInstallerService.ts +474 -0
- package/src/services/tomcat/TomcatMirrorManager.ts +181 -0
- package/src/services/tomcat/index.ts +36 -0
- package/src/services/tomcat/types.ts +120 -0
- package/src/types/args.ts +68 -1
- package/src/types/configSchema.ts +174 -0
- package/src/utils/ChangelogGenerator.ts +11 -11
- package/src/utils/LoggerLevel.ts +44 -20
- package/src/utils/ProgressBar.ts +87 -46
- package/src/utils/argsParser.ts +260 -0
- package/src/utils/config.ts +340 -189
- package/src/utils/constants.ts +87 -9
- package/src/utils/dryRun.ts +192 -0
- package/src/utils/processManager.ts +23 -7
- package/src/utils/security.ts +293 -0
- package/src/utils/ui.ts +299 -428
|
@@ -1,233 +1,246 @@
|
|
|
1
1
|
import type { Command } from "./Command";
|
|
2
2
|
import type { AppConfig, CLIArguments } from "../types/config";
|
|
3
|
-
import { Logger } from "../
|
|
3
|
+
import { Logger } from "../logging";
|
|
4
4
|
import fs from "fs";
|
|
5
5
|
import path from "path";
|
|
6
6
|
import os from "os";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
getCatalinaScript,
|
|
9
|
+
getWhichCommand,
|
|
10
|
+
getJbrDownloadUrl,
|
|
11
|
+
getTarExtractCommand,
|
|
12
|
+
getJavaPath,
|
|
13
|
+
getJavaBinary,
|
|
14
|
+
isWindows,
|
|
15
|
+
isLinux,
|
|
16
|
+
isMacOS,
|
|
17
17
|
} from "../utils/platform";
|
|
18
18
|
|
|
19
19
|
export class DoctorCommand implements Command {
|
|
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
|
-
|
|
20
|
+
private logger = Logger.getInstance();
|
|
21
|
+
|
|
22
|
+
async execute(config: AppConfig, values: CLIArguments = {}): Promise<void> {
|
|
23
|
+
this.logger.section("Xavva Doctor - Diagnóstico");
|
|
24
|
+
|
|
25
|
+
// Se modo fix, mostra aviso
|
|
26
|
+
if (values.fix) {
|
|
27
|
+
this.logger.warn("Modo --fix ativado - Problemas serão corrigidos automaticamente");
|
|
28
|
+
this.logger.newline();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const issues: Array<{ label: string; ok: boolean; detail: string; fixable?: boolean }> = [];
|
|
32
|
+
|
|
33
|
+
// Verifica JAVA_HOME
|
|
34
|
+
const javaHomeOk = !!process.env.JAVA_HOME;
|
|
35
|
+
issues.push({
|
|
36
|
+
label: "JAVA_HOME",
|
|
37
|
+
ok: javaHomeOk,
|
|
38
|
+
detail: process.env.JAVA_HOME || "Não definido",
|
|
39
|
+
fixable: true,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const jvmInfo = this.checkJVM();
|
|
43
|
+
this.check(
|
|
44
|
+
"JVM Type",
|
|
45
|
+
jvmInfo.dcevm,
|
|
46
|
+
jvmInfo.name +
|
|
47
|
+
(jvmInfo.dcevm ? " (Advanced Hot Reload OK)" : " (Standard)"),
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if (!jvmInfo.dcevm) {
|
|
51
|
+
console.log(
|
|
52
|
+
` 💡 Dica: Sua JVM não suporta mudanças estruturais (novos métodos/campos).`,
|
|
53
|
+
);
|
|
54
|
+
if (values.fix) {
|
|
55
|
+
await this.installDCEVM();
|
|
56
|
+
} else {
|
|
57
|
+
console.log(
|
|
58
|
+
` Use 'xavva doctor --fix' para baixar uma JDK com DCEVM integrado.`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const tomcatOk = fs.existsSync(config.tomcat.path);
|
|
64
|
+
this.check("Tomcat Path", tomcatOk, config.tomcat.path);
|
|
65
|
+
|
|
66
|
+
if (tomcatOk) {
|
|
67
|
+
const binOk = fs.existsSync(
|
|
68
|
+
path.join(config.tomcat.path, "bin", getCatalinaScript()),
|
|
69
|
+
);
|
|
70
|
+
this.check(
|
|
71
|
+
"Tomcat Bin",
|
|
72
|
+
binOk,
|
|
73
|
+
binOk ? "OK" : `${getCatalinaScript()} não encontrado`,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const mvnOk = this.checkBinary("mvn");
|
|
78
|
+
this.check("Maven", mvnOk, mvnOk ? "Disponível" : "Não encontrado no PATH");
|
|
79
|
+
|
|
80
|
+
const gradleOk = this.checkBinary("gradle") || this.checkBinary("gradlew");
|
|
81
|
+
this.check(
|
|
82
|
+
"Gradle",
|
|
83
|
+
gradleOk,
|
|
84
|
+
gradleOk ? "Disponível" : "Não encontrado no PATH",
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const gitOk = this.checkBinary("git");
|
|
88
|
+
this.check("Git", gitOk, gitOk ? "Disponível" : "Não encontrado no PATH");
|
|
89
|
+
|
|
90
|
+
this.logger.section("Xavva Doctor - Integridade de Arquivos");
|
|
91
|
+
await this.checkJarIntegrity(values.fix, config);
|
|
92
|
+
await this.checkBOM(values.fix);
|
|
93
|
+
|
|
94
|
+
console.log("");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private async checkJarIntegrity(fix: boolean, config: AppConfig) {
|
|
98
|
+
const searchPaths = [
|
|
99
|
+
path.join(process.cwd(), "target"),
|
|
100
|
+
path.join(process.cwd(), "build"),
|
|
101
|
+
path.join(config.tomcat.path, "webapps")
|
|
102
|
+
].filter(p => fs.existsSync(p));
|
|
103
|
+
|
|
104
|
+
const corruptedJars: string[] = [];
|
|
105
|
+
const zipEndSignature = Buffer.from([0x50, 0x4b, 0x05, 0x06]);
|
|
106
|
+
|
|
107
|
+
const scan = (dir: string) => {
|
|
108
|
+
try {
|
|
109
|
+
const list = fs.readdirSync(dir, { withFileTypes: true });
|
|
110
|
+
for (const item of list) {
|
|
111
|
+
const res = path.resolve(dir, item.name);
|
|
112
|
+
if (item.isDirectory()) {
|
|
113
|
+
if (item.name === "node_modules" || item.name === ".git") continue;
|
|
114
|
+
scan(res);
|
|
115
|
+
} else if (item.name.endsWith(".jar")) {
|
|
116
|
+
try {
|
|
117
|
+
const stats = fs.statSync(res);
|
|
118
|
+
if (stats.size < 22) {
|
|
119
|
+
corruptedJars.push(res);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Lê os últimos 1024 bytes para encontrar a assinatura EOCD do ZIP
|
|
124
|
+
const readSize = Math.min(stats.size, 1024);
|
|
125
|
+
const buffer = Buffer.alloc(readSize);
|
|
126
|
+
const fd = fs.openSync(res, "r");
|
|
127
|
+
fs.readSync(fd, buffer, 0, readSize, stats.size - readSize);
|
|
128
|
+
fs.closeSync(fd);
|
|
129
|
+
|
|
130
|
+
if (!buffer.includes(zipEndSignature)) {
|
|
131
|
+
corruptedJars.push(res);
|
|
132
|
+
}
|
|
133
|
+
} catch (e) {
|
|
134
|
+
corruptedJars.push(res);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} catch (e) {}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
for (const p of searchPaths) {
|
|
142
|
+
scan(p);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (corruptedJars.length > 0) {
|
|
146
|
+
this.check(
|
|
147
|
+
"Integridade JAR",
|
|
148
|
+
false,
|
|
149
|
+
`${corruptedJars.length} arquivos corrompidos detectados.`,
|
|
150
|
+
);
|
|
151
|
+
if (fix) {
|
|
152
|
+
for (const file of corruptedJars) {
|
|
153
|
+
try {
|
|
154
|
+
fs.unlinkSync(file);
|
|
155
|
+
console.log(` ✔ Removido: ${path.basename(file)}`);
|
|
156
|
+
} catch (e) {}
|
|
157
|
+
}
|
|
158
|
+
this.logger.success("JARs corrompidos removidos! Eles serão reconstruídos no próximo build.");
|
|
159
|
+
|
|
160
|
+
// Limpar cache do Tomcat
|
|
161
|
+
this.logger.step("Limpando cache do Tomcat (work/temp)...");
|
|
162
|
+
const tomcatWork = path.join(config.tomcat.path, "work");
|
|
163
|
+
const tomcatTemp = path.join(config.tomcat.path, "temp");
|
|
164
|
+
[tomcatWork, tomcatTemp].forEach(p => {
|
|
165
|
+
try {
|
|
166
|
+
if (fs.existsSync(p)) {
|
|
167
|
+
fs.rmSync(p, { recursive: true, force: true });
|
|
168
|
+
fs.mkdirSync(p);
|
|
169
|
+
}
|
|
170
|
+
} catch (e) {}
|
|
171
|
+
});
|
|
172
|
+
this.logger.success("Cache do Tomcat limpo com sucesso.");
|
|
173
|
+
} else {
|
|
174
|
+
this.logger.warn(
|
|
175
|
+
"Use 'xavva doctor --fix' para remover os JARs corrompidos e limpar o cache.",
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
this.check("Integridade JAR", true, "Todos os arquivos JAR parecem íntegros.");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private async checkBOM(fix: boolean) {
|
|
184
|
+
const srcPath = path.join(process.cwd(), "src");
|
|
185
|
+
if (!fs.existsSync(srcPath)) return;
|
|
186
|
+
|
|
187
|
+
const filesWithBOM: string[] = [];
|
|
188
|
+
const scan = (dir: string) => {
|
|
189
|
+
const list = fs.readdirSync(dir, { withFileTypes: true });
|
|
190
|
+
for (const item of list) {
|
|
191
|
+
const res = path.resolve(dir, item.name);
|
|
192
|
+
if (item.isDirectory()) {
|
|
193
|
+
scan(res);
|
|
194
|
+
} else if (item.name.endsWith(".java")) {
|
|
195
|
+
const buffer = fs.readFileSync(res);
|
|
196
|
+
if (buffer[0] === 0xef && buffer[1] === 0xbb && buffer[2] === 0xbf) {
|
|
197
|
+
filesWithBOM.push(res);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
scan(srcPath);
|
|
204
|
+
|
|
205
|
+
if (filesWithBOM.length > 0) {
|
|
206
|
+
this.check(
|
|
207
|
+
"Encoding BOM",
|
|
208
|
+
false,
|
|
209
|
+
`${filesWithBOM.length} arquivos com BOM (UTF-8 com assinatura)`,
|
|
210
|
+
);
|
|
211
|
+
if (fix) {
|
|
212
|
+
for (const file of filesWithBOM) {
|
|
213
|
+
const buffer = fs.readFileSync(file);
|
|
214
|
+
const cleanBuffer = buffer.subarray(3);
|
|
215
|
+
fs.writeFileSync(file, cleanBuffer);
|
|
216
|
+
console.log(
|
|
217
|
+
` ✔ Corrigido: ${path.basename(file)}`,
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
this.logger.success("BOM removido de todos os arquivos!");
|
|
221
|
+
} else {
|
|
222
|
+
this.logger.warn(
|
|
223
|
+
"Use 'xavva doctor --fix' para remover o BOM automaticamente.",
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
this.check("Encoding BOM", true, "Nenhum arquivo com BOM detectado.");
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private check(label: string, ok: boolean, detail: string) {
|
|
232
|
+
const icon = ok ? "✔" : "✘";
|
|
233
|
+
console.log(` ${icon} ${label.padEnd(15)} ${detail}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private checkBinary(name: string): boolean {
|
|
237
|
+
try {
|
|
238
|
+
const proc = Bun.spawnSync(getWhichCommand(name));
|
|
239
|
+
return proc.exitCode === 0;
|
|
240
|
+
} catch {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
231
244
|
|
|
232
245
|
private checkJVM(): { name: string, dcevm: boolean } {
|
|
233
246
|
try {
|
|
@@ -252,8 +265,8 @@ export class DoctorCommand implements Command {
|
|
|
252
265
|
}
|
|
253
266
|
|
|
254
267
|
private async installDCEVM() {
|
|
255
|
-
|
|
256
|
-
|
|
268
|
+
this.logger.section("Instalação do JetBrains Runtime (JBR 21)");
|
|
269
|
+
this.logger.step("Baixando JDK moderna com DCEVM nativo (JBR 21 SDK)...");
|
|
257
270
|
|
|
258
271
|
// URL para o JetBrains Runtime 21 SDK (multiplataforma)
|
|
259
272
|
const url = getJbrDownloadUrl("21");
|
|
@@ -274,7 +287,7 @@ export class DoctorCommand implements Command {
|
|
|
274
287
|
const tarPath = path.join(installDir, "jbr.tar.gz");
|
|
275
288
|
fs.writeFileSync(tarPath, Buffer.from(buffer));
|
|
276
289
|
|
|
277
|
-
|
|
290
|
+
this.logger.success("Download concluído. Extraindo binários...");
|
|
278
291
|
|
|
279
292
|
// Extrair .tar.gz usando comando apropriado para a plataforma
|
|
280
293
|
const extractCmd = getTarExtractCommand(tarPath, installDir);
|
|
@@ -304,12 +317,12 @@ export class DoctorCommand implements Command {
|
|
|
304
317
|
await this.configureUnixEnv(jdkPath, binPath);
|
|
305
318
|
}
|
|
306
319
|
} catch (e: any) {
|
|
307
|
-
|
|
320
|
+
this.logger.error(`Falha na instalação: ${e.message}`);
|
|
308
321
|
}
|
|
309
322
|
}
|
|
310
323
|
|
|
311
324
|
private async configureWindowsEnv(jdkPath: string, binPath: string) {
|
|
312
|
-
|
|
325
|
+
this.logger.step("Configurando variáveis de ambiente do SISTEMA...");
|
|
313
326
|
|
|
314
327
|
const setEnvCmd = `
|
|
315
328
|
$jdk = $env:JDK_PATH;
|
|
@@ -345,20 +358,20 @@ export class DoctorCommand implements Command {
|
|
|
345
358
|
const output = result.stdout.toString() + result.stderr.toString();
|
|
346
359
|
|
|
347
360
|
if (output.includes("ACCESS_DENIED")) {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
361
|
+
this.logger.error("Falha ao configurar variáveis do SISTEMA (Acesso Negado).");
|
|
362
|
+
this.logger.warn("Dica: Execute o terminal como ADMINISTRADOR para permitir esta alteração.");
|
|
363
|
+
this.logger.config("JAVA_HOME manual", jdkPath);
|
|
351
364
|
} else {
|
|
352
|
-
|
|
353
|
-
|
|
365
|
+
this.logger.success(`DCEVM configurado no SISTEMA com sucesso!`);
|
|
366
|
+
this.logger.config("JAVA_HOME", jdkPath);
|
|
354
367
|
}
|
|
355
368
|
|
|
356
|
-
|
|
357
|
-
|
|
369
|
+
this.logger.newline();
|
|
370
|
+
this.logger.warn("IMPORTANTE: Reinicie seu terminal (ou o VS Code) para as mudanças surtirem efeito.");
|
|
358
371
|
}
|
|
359
372
|
|
|
360
373
|
private async configureUnixEnv(jdkPath: string, binPath: string) {
|
|
361
|
-
|
|
374
|
+
this.logger.step("Configurando variáveis de ambiente...");
|
|
362
375
|
|
|
363
376
|
const shell = process.env.SHELL || "/bin/bash";
|
|
364
377
|
let rcFile = path.join(os.homedir(), ".bashrc");
|
|
@@ -393,11 +406,11 @@ export class DoctorCommand implements Command {
|
|
|
393
406
|
|
|
394
407
|
fs.writeFileSync(rcFile, filteredLines.join("\n") + "\n");
|
|
395
408
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
409
|
+
this.logger.success(`DCEVM configurado em ${rcFile}`);
|
|
410
|
+
this.logger.config("JAVA_HOME", jdkPath);
|
|
411
|
+
this.logger.newline();
|
|
412
|
+
this.logger.warn("IMPORTANTE: Execute 'source " + rcFile + "' ou reinicie seu terminal para aplicar permanentemente.");
|
|
413
|
+
this.logger.info("Dica: Para esta sessão, o JAVA_HOME já foi configurado temporariamente.");
|
|
401
414
|
|
|
402
415
|
// Configura JAVA_HOME temporariamente para o processo atual
|
|
403
416
|
process.env.JAVA_HOME = jdkPath;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Command } from "./Command";
|
|
2
2
|
import type { AppConfig, CLIArguments } from "../types/config";
|
|
3
3
|
import { EncodingService } from "../services/EncodingService";
|
|
4
|
-
import { Logger } from "../utils/ui";
|
|
4
|
+
import { Logger, C } from "../utils/ui";
|
|
5
5
|
import path from "path";
|
|
6
6
|
import { existsSync } from "fs";
|
|
7
7
|
import { ProcessManager } from "../utils/processManager";
|
|
@@ -54,19 +54,19 @@ export class EncodingCommand implements Command {
|
|
|
54
54
|
Logger.log("Gerencia conversão de encoding de arquivos de texto");
|
|
55
55
|
Logger.newline();
|
|
56
56
|
|
|
57
|
-
Logger.log(`${
|
|
57
|
+
Logger.log(`${C.primary}Uso:${C.reset}`);
|
|
58
58
|
Logger.log(" xavva encoding <subcomando> [arquivo] [opções]");
|
|
59
59
|
Logger.newline();
|
|
60
60
|
|
|
61
|
-
Logger.log(`${
|
|
62
|
-
Logger.log(` ${
|
|
63
|
-
Logger.log(` ${
|
|
64
|
-
Logger.log(` ${
|
|
65
|
-
Logger.log(` ${
|
|
66
|
-
Logger.log(` ${
|
|
61
|
+
Logger.log(`${C.primary}Subcomandos:${C.reset}`);
|
|
62
|
+
Logger.log(` ${C.secondary}detect${C.reset} [arquivo] Detecta encoding de um arquivo ou diretório`);
|
|
63
|
+
Logger.log(` ${C.secondary}convert${C.reset} [arquivo] Converte arquivo(s) para outro encoding`);
|
|
64
|
+
Logger.log(` ${C.secondary}fix${C.reset} [arquivo] Tenta corrigir mojibake automaticamente`);
|
|
65
|
+
Logger.log(` ${C.secondary}list${C.reset} Lista encodings de todos os arquivos do projeto`);
|
|
66
|
+
Logger.log(` ${C.secondary}help${C.reset} Mostra esta ajuda`);
|
|
67
67
|
Logger.newline();
|
|
68
68
|
|
|
69
|
-
Logger.log(`${
|
|
69
|
+
Logger.log(`${C.primary}Opções:${C.reset}`);
|
|
70
70
|
Logger.log(` --from <encoding> Encoding de origem (padrão: auto-detect)`);
|
|
71
71
|
Logger.log(` --to <encoding> Encoding de destino (padrão: do xavva.json ou UTF-8)`);
|
|
72
72
|
Logger.log(` --backup Cria backup antes de converter`);
|
|
@@ -75,13 +75,13 @@ export class EncodingCommand implements Command {
|
|
|
75
75
|
Logger.log(` --src <path> Diretório fonte (padrão: src/)`);
|
|
76
76
|
Logger.newline();
|
|
77
77
|
|
|
78
|
-
Logger.log(`${
|
|
78
|
+
Logger.log(`${C.primary}Encodings suportados:${C.reset}`);
|
|
79
79
|
Logger.log(` utf-8, utf8 UTF-8 (padrão)`);
|
|
80
80
|
Logger.log(` windows-1252, cp1252 Windows CP1252 (ANSI)`);
|
|
81
81
|
Logger.log(` iso-8859-1, latin1 ISO-8859-1 (Latin-1)`);
|
|
82
82
|
Logger.newline();
|
|
83
83
|
|
|
84
|
-
Logger.log(`${
|
|
84
|
+
Logger.log(`${C.primary}Exemplos:${C.reset}`);
|
|
85
85
|
Logger.log(` xavva encoding detect src/main/java/MinhaClasse.java`);
|
|
86
86
|
Logger.log(` xavva encoding convert --from utf-8 --to cp1252 src/main/java/`);
|
|
87
87
|
Logger.log(` xavva encoding convert --to cp1252 --backup src/main/java/MinhaClasse.java`);
|
|
@@ -135,13 +135,13 @@ export class EncodingCommand implements Command {
|
|
|
135
135
|
Logger.info("Arquivos analisados", String(detections.size));
|
|
136
136
|
Logger.newline();
|
|
137
137
|
|
|
138
|
-
Logger.log(`${
|
|
138
|
+
Logger.log(`${C.primary}Distribuição por encoding:${C.reset}`);
|
|
139
139
|
for (const [encoding, count] of byEncoding) {
|
|
140
140
|
Logger.config(encoding, `${count} arquivo(s)`);
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
Logger.newline();
|
|
144
|
-
Logger.log(`${
|
|
144
|
+
Logger.log(`${C.primary}Arquivos com baixa confiança:${C.reset}`);
|
|
145
145
|
let lowConfidenceFound = false;
|
|
146
146
|
for (const [file, detection] of detections) {
|
|
147
147
|
if (detection.confidence < 0.8) {
|
|
@@ -339,18 +339,18 @@ export class EncodingCommand implements Command {
|
|
|
339
339
|
// Ordena arquivos
|
|
340
340
|
const sortedFiles = Array.from(detections.entries()).sort((a, b) => a[0].localeCompare(b[0]));
|
|
341
341
|
|
|
342
|
-
Logger.log(`${
|
|
342
|
+
Logger.log(`${C.primary}Arquivos:${C.reset}`);
|
|
343
343
|
for (const [file, detection] of sortedFiles) {
|
|
344
344
|
const relativePath = path.relative(srcDir, file);
|
|
345
345
|
const confidenceStr = detection.confidence >= 0.9 ? "" :
|
|
346
|
-
` ${
|
|
347
|
-
const bomStr = detection.hasBOM ? ` ${
|
|
346
|
+
` ${C.gray}(${Math.round(detection.confidence * 100)}%)${C.reset}`;
|
|
347
|
+
const bomStr = detection.hasBOM ? ` ${C.warning}[BOM]${C.reset}` : "";
|
|
348
348
|
|
|
349
349
|
const encodingColor = detection.encoding === (config.project.encoding || "utf-8")
|
|
350
|
-
?
|
|
351
|
-
:
|
|
350
|
+
? C.success
|
|
351
|
+
: C.warning;
|
|
352
352
|
|
|
353
|
-
Logger.log(` ${encodingColor}${detection.encoding.padEnd(12)}${
|
|
353
|
+
Logger.log(` ${encodingColor}${detection.encoding.padEnd(12)}${C.reset} ${relativePath}${confidenceStr}${bomStr}`);
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
Logger.endSection();
|