@archznn/xavva 1.8.0 → 1.8.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
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# XAVVA 🚀 (Windows Only) `v1.8.
|
|
1
|
+
# XAVVA 🚀 (Windows Only) `v1.8.1`
|
|
2
2
|
|
|
3
3
|
Xavva é uma CLI de alto desempenho construída com **Bun** para automatizar o ciclo de desenvolvimento de aplicações Java (Maven/Gradle) rodando no Apache Tomcat. Ela foi desenhada especificamente para desenvolvedores que buscam a velocidade de ambientes modernos (como Node.js/Vite) dentro do ecossistema Java Enterprise.
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -27,16 +27,13 @@ export class DeployCommand implements Command {
|
|
|
27
27
|
const contextPath = (config.project.appName || "").replace(".war", "");
|
|
28
28
|
|
|
29
29
|
if (!incremental) {
|
|
30
|
-
tomcat.
|
|
30
|
+
await tomcat.killConflict();
|
|
31
|
+
await tomcat.clearWebapps();
|
|
31
32
|
|
|
32
|
-
const buildTask = config.project.skipBuild ? Promise.resolve() : builder.runBuild(incremental);
|
|
33
|
-
const killTask = tomcat.killConflict();
|
|
34
|
-
|
|
35
33
|
if (!config.project.skipBuild) {
|
|
36
|
-
Logger.watcher("
|
|
34
|
+
Logger.watcher("Building project", "start");
|
|
35
|
+
await builder.runBuild(incremental);
|
|
37
36
|
}
|
|
38
|
-
|
|
39
|
-
await Promise.all([buildTask, killTask]);
|
|
40
37
|
|
|
41
38
|
if (!config.project.skipBuild) {
|
|
42
39
|
Logger.build("Full project build and environment ready");
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Command } from "./Command";
|
|
2
2
|
import type { AppConfig, CLIArguments } from "../types/config";
|
|
3
3
|
import { Logger } from "../utils/ui";
|
|
4
|
-
import { spawn } from "child_process";
|
|
5
4
|
import path from "path";
|
|
6
5
|
|
|
7
6
|
export class RunCommand implements Command {
|
|
@@ -54,19 +53,20 @@ export class RunCommand implements Command {
|
|
|
54
53
|
Logger.warn(`🚀 Executando ${className}...`);
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
const bin = process.env.JAVA_HOME ? path.join(process.env.JAVA_HOME, "bin", "java") : "java";
|
|
56
|
+
const bin = process.env.JAVA_HOME ? path.join(process.env.JAVA_HOME, "bin", "java.exe") : "java";
|
|
58
57
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
resolve();
|
|
68
|
-
});
|
|
58
|
+
const proc = Bun.spawn([bin, ...javaArgs], {
|
|
59
|
+
stdout: "inherit",
|
|
60
|
+
stderr: "inherit",
|
|
61
|
+
stdin: "inherit",
|
|
62
|
+
env: {
|
|
63
|
+
...process.env,
|
|
64
|
+
JAVA_OPTS: "-Xms256m -Xmx1024m"
|
|
65
|
+
} as any
|
|
69
66
|
});
|
|
67
|
+
|
|
68
|
+
await proc.exited;
|
|
69
|
+
Logger.log(`Sessão de ${isDebug ? "debug" : "execução"} encerrada.`);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
private async discoverClass(simpleName: string): Promise<string | null> {
|
|
@@ -41,7 +41,7 @@ export class BuildCacheService {
|
|
|
41
41
|
return crypto.createHash("md5").update(hash).digest("hex");
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
shouldRebuild(tool: "maven" | "gradle"): boolean {
|
|
44
|
+
shouldRebuild(tool: "maven" | "gradle", projectService?: any): boolean {
|
|
45
45
|
if (!fs.existsSync(this.cacheFile)) return true;
|
|
46
46
|
|
|
47
47
|
try {
|
|
@@ -51,8 +51,16 @@ export class BuildCacheService {
|
|
|
51
51
|
// Se o pom/gradle mudou, precisa de rebuild completo
|
|
52
52
|
if (currentHash !== cache.lastConfigHash) return true;
|
|
53
53
|
|
|
54
|
-
// Verificar se o artefato (.war) ainda existe
|
|
55
|
-
|
|
54
|
+
// Verificar se o artefato (.war) ainda existe fisicamente
|
|
55
|
+
if (projectService) {
|
|
56
|
+
try {
|
|
57
|
+
const artifact = projectService.getArtifact();
|
|
58
|
+
if (!fs.existsSync(artifact.path)) return true;
|
|
59
|
+
} catch (e) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
56
64
|
return false;
|
|
57
65
|
} catch (e) {
|
|
58
66
|
return true;
|
|
@@ -19,16 +19,22 @@ export class BuildService {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
if (!incremental && !this.projectConfig.skipBuild) {
|
|
22
|
-
if (!this.projectConfig.clean && !this.cache.shouldRebuild(this.projectConfig.buildTool)) {
|
|
22
|
+
if (!this.projectConfig.clean && !this.cache.shouldRebuild(this.projectConfig.buildTool, this.projectService)) {
|
|
23
23
|
Logger.success("Build cache hit! Skipping full build.");
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const command = [];
|
|
29
|
+
const env = { ...process.env };
|
|
29
30
|
|
|
30
31
|
if (this.projectConfig.buildTool === 'maven') {
|
|
31
32
|
command.push("mvn");
|
|
33
|
+
|
|
34
|
+
if (!this.cache.shouldRebuild('maven', this.projectService)) {
|
|
35
|
+
command.push("-o");
|
|
36
|
+
}
|
|
37
|
+
|
|
32
38
|
if (incremental) {
|
|
33
39
|
command.push("compile");
|
|
34
40
|
} else {
|
|
@@ -38,6 +44,8 @@ export class BuildService {
|
|
|
38
44
|
}
|
|
39
45
|
command.push("-Dmaven.test.skip=true", "-Dmaven.javadoc.skip=true");
|
|
40
46
|
if (this.projectConfig.profile) command.push(`-P${this.projectConfig.profile}`);
|
|
47
|
+
|
|
48
|
+
env.MAVEN_OPTS = "-Xms512m -Xmx1024m -XX:+UseParallelGC";
|
|
41
49
|
} else {
|
|
42
50
|
command.push("gradle");
|
|
43
51
|
if (incremental) {
|
|
@@ -49,13 +57,16 @@ export class BuildService {
|
|
|
49
57
|
}
|
|
50
58
|
command.push("-x", "test", "-x", "javadoc");
|
|
51
59
|
if (this.projectConfig.profile) command.push(`-Pprofile=${this.projectConfig.profile}`);
|
|
60
|
+
|
|
61
|
+
env.GRADLE_OPTS = "-Xmx1024m -Dorg.gradle.daemon=true";
|
|
52
62
|
}
|
|
53
63
|
|
|
54
64
|
const stopSpinner = (this.projectConfig.verbose) ? () => {} : Logger.spinner(incremental ? "Incremental compilation" : "Full project build");
|
|
55
65
|
|
|
56
66
|
const proc = Bun.spawn(command, {
|
|
57
67
|
stdout: "pipe",
|
|
58
|
-
stderr: "pipe"
|
|
68
|
+
stderr: "pipe",
|
|
69
|
+
env: env as any
|
|
59
70
|
});
|
|
60
71
|
|
|
61
72
|
if (this.projectConfig.verbose) {
|
|
@@ -42,28 +42,45 @@ export class TomcatService {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
clearWebapps() {
|
|
46
|
-
const fs = require("fs");
|
|
45
|
+
async clearWebapps() {
|
|
46
|
+
const fs = require("fs").promises;
|
|
47
|
+
const { existsSync } = require("fs");
|
|
47
48
|
const path = require("path");
|
|
48
49
|
const webappsPath = path.join(this.activeConfig.path, "webapps");
|
|
49
50
|
const workPath = path.join(this.activeConfig.path, "work");
|
|
50
51
|
const tempPath = path.join(this.activeConfig.path, "temp");
|
|
51
52
|
|
|
52
53
|
try {
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
fs.
|
|
56
|
-
|
|
54
|
+
const cleanDir = async (p: string) => {
|
|
55
|
+
if (existsSync(p)) {
|
|
56
|
+
await fs.rm(p, { recursive: true, force: true });
|
|
57
|
+
|
|
58
|
+
// Resiliência para Windows: garante que o diretório foi liberado antes do mkdir
|
|
59
|
+
let retries = 10;
|
|
60
|
+
while (retries > 0 && existsSync(p)) {
|
|
61
|
+
await new Promise(r => setTimeout(r, 50));
|
|
62
|
+
retries--;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
await fs.mkdir(p, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const tasks: Promise<any>[] = [
|
|
70
|
+
cleanDir(workPath),
|
|
71
|
+
cleanDir(tempPath)
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
if (existsSync(webappsPath)) {
|
|
75
|
+
const files = await fs.readdir(webappsPath);
|
|
76
|
+
for (const file of files) {
|
|
77
|
+
if (file === "ROOT" || file === "manager" || file === "host-manager") continue;
|
|
78
|
+
const fullPath = path.join(webappsPath, file);
|
|
79
|
+
tasks.push(fs.rm(fullPath, { recursive: true, force: true }));
|
|
57
80
|
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const files = fs.readdirSync(webappsPath);
|
|
61
|
-
for (const file of files) {
|
|
62
|
-
const fullPath = path.join(webappsPath, file);
|
|
63
|
-
if (file === "ROOT" || file === "manager" || file === "host-manager") continue;
|
|
64
|
-
|
|
65
|
-
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
66
81
|
}
|
|
82
|
+
|
|
83
|
+
await Promise.all(tasks);
|
|
67
84
|
} catch (e) {
|
|
68
85
|
Logger.warn("Não foi possível limpar totalmente a pasta webapps ou cache.");
|
|
69
86
|
}
|