@archznn/xavva 3.1.2 → 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 +43 -14
- package/src/commands/DeployCommand.ts +252 -229
- package/src/commands/DepsCommand.ts +174 -174
- package/src/commands/DockerCommand.ts +35 -4
- package/src/commands/DoctorCommand.ts +252 -239
- package/src/commands/EncodingCommand.ts +26 -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 +27 -1
- 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 +25 -1
- package/src/commands/TomcatCommand.ts +232 -88
- 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 +20 -6
- 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
|
@@ -4,7 +4,7 @@ import type { Command } from "./Command";
|
|
|
4
4
|
import type { AppConfig, CLIArguments } from "../types/config";
|
|
5
5
|
import { BuildService } from "../services/BuildService";
|
|
6
6
|
import { TomcatService } from "../services/TomcatService";
|
|
7
|
-
import { Logger } from "../
|
|
7
|
+
import { Logger, OperationLogger } from "../logging";
|
|
8
8
|
import { EndpointService } from "../services/EndpointService";
|
|
9
9
|
import { BrowserService } from "../services/BrowserService";
|
|
10
10
|
import {
|
|
@@ -14,260 +14,283 @@ import {
|
|
|
14
14
|
} from "../utils/platform";
|
|
15
15
|
|
|
16
16
|
export class DeployCommand implements Command {
|
|
17
|
-
|
|
17
|
+
private logger = Logger.getInstance();
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
const incremental = args?.watch && args?.incremental;
|
|
21
|
-
const isWatching = !!args?.watch;
|
|
22
|
-
const changedFiles = args?.changedFiles;
|
|
23
|
-
const tomcat = this.tomcat;
|
|
24
|
-
const builder = this.builder;
|
|
19
|
+
constructor(private tomcat: TomcatService, private builder: BuildService) {}
|
|
25
20
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
const contextPath = (config.project.appName || "").replace(".war", "");
|
|
21
|
+
async execute(config: AppConfig, args?: CLIArguments): Promise<void> {
|
|
22
|
+
const incremental = args?.watch && args?.incremental;
|
|
23
|
+
const isWatching = !!args?.watch;
|
|
24
|
+
const changedFiles = args?.changedFiles;
|
|
25
|
+
const tomcat = this.tomcat;
|
|
26
|
+
const builder = this.builder;
|
|
34
27
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
await tomcat.clearWebapps();
|
|
28
|
+
// Cria operação para rastreamento
|
|
29
|
+
const operation = new OperationLogger(incremental ? 'hot-reload' : 'deploy');
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
} else {
|
|
48
|
-
if (!config.project.skipBuild) {
|
|
49
|
-
Logger.build("incremental compile...");
|
|
50
|
-
await builder.runBuild(incremental);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
31
|
+
if (!incremental) {
|
|
32
|
+
this.logConfiguration(config, isWatching);
|
|
33
|
+
} else {
|
|
34
|
+
this.logger.debug("Mudança detectada");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const contextPath = (config.project.appName || "").replace(".war", "");
|
|
53
39
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Logger.success(`redeploy completed (${changedFiles?.length || 'all'} file(s))`);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
40
|
+
if (!incremental) {
|
|
41
|
+
operation.start('Iniciando deploy');
|
|
42
|
+
|
|
43
|
+
await tomcat.killConflict();
|
|
44
|
+
await tomcat.clearWebapps();
|
|
62
45
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
46
|
+
if (!config.project.skipBuild) {
|
|
47
|
+
const buildStep = operation.step('build', 'Compilando projeto...');
|
|
48
|
+
await builder.runBuild(incremental);
|
|
49
|
+
buildStep.success('Compilação concluída');
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
if (!config.project.skipBuild) {
|
|
53
|
+
this.logger.debug('Compilação incremental...');
|
|
54
|
+
await builder.runBuild(incremental);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
69
57
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
58
|
+
if (incremental) {
|
|
59
|
+
const syncStep = operation.step('sync', 'Sincronizando classes...');
|
|
60
|
+
const actualAppFolder = await builder.syncClasses(changedFiles);
|
|
61
|
+
const actualContextPath = contextPath || actualAppFolder || "";
|
|
62
|
+
const actualAppUrl = `http://localhost:${config.tomcat.port}/${actualContextPath}`;
|
|
63
|
+
await BrowserService.reload(actualAppUrl);
|
|
64
|
+
|
|
65
|
+
const fileCount = changedFiles?.length || 0;
|
|
66
|
+
if (fileCount > 0) {
|
|
67
|
+
syncStep.success(`${fileCount} arquivo(s) sincronizado(s)`);
|
|
68
|
+
this.logger.success(`Hot-reload concluído`);
|
|
69
|
+
} else {
|
|
70
|
+
syncStep.success('Hot-reload concluído');
|
|
71
|
+
}
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
77
74
|
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
const deployStep = operation.step('deploy', 'Preparando deploy...');
|
|
76
|
+
const artifactInfo = await builder.deployToWebapps();
|
|
77
|
+
|
|
78
|
+
const finalContextPath = contextPath || artifactInfo.finalName.replace(".war", "");
|
|
79
|
+
const appWebappPath = path.join(config.tomcat.path, "webapps", finalContextPath);
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const extractCmd = `Expand-Archive -Path $env:ARTIFACT_PATH -DestinationPath $env:DEST_PATH -Force`;
|
|
89
|
-
Bun.spawnSync(["powershell", "-command", extractCmd], {
|
|
90
|
-
env: {
|
|
91
|
-
...process.env,
|
|
92
|
-
ARTIFACT_PATH: artifactInfo.path,
|
|
93
|
-
DEST_PATH: appWebappPath
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
} else {
|
|
97
|
-
// Linux/Mac: usa unzip ou jar
|
|
98
|
-
try {
|
|
99
|
-
Bun.spawnSync(["unzip", "-q", "-o", artifactInfo.path, "-d", appWebappPath]);
|
|
100
|
-
} catch {
|
|
101
|
-
// Fallback final para jar
|
|
102
|
-
Bun.spawnSync(getWarExtractCommand(artifactInfo.path, appWebappPath), {
|
|
103
|
-
cwd: appWebappPath
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
Logger.server("extracted WAR (fallback)");
|
|
108
|
-
}
|
|
109
|
-
} else {
|
|
110
|
-
Logger.server("webapp up to date");
|
|
111
|
-
}
|
|
112
|
-
}
|
|
81
|
+
if (artifactInfo.isDirectory) {
|
|
82
|
+
// Se é um diretório (exploded), sincronizamos o conteúdo total para a pasta do webapps
|
|
83
|
+
if (!fs.existsSync(appWebappPath)) fs.mkdirSync(appWebappPath, { recursive: true });
|
|
84
|
+
await builder.syncExploded(artifactInfo.path, appWebappPath);
|
|
85
|
+
deployStep.update('Diretório exploded sincronizado');
|
|
86
|
+
} else {
|
|
87
|
+
if (!fs.existsSync(appWebappPath)) fs.mkdirSync(appWebappPath, { recursive: true });
|
|
113
88
|
|
|
114
|
-
|
|
115
|
-
|
|
89
|
+
const artifactStat = fs.statSync(artifactInfo.path);
|
|
90
|
+
const webappStat = fs.existsSync(appWebappPath) ? fs.statSync(appWebappPath) : null;
|
|
116
91
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
92
|
+
if (!webappStat || artifactStat.mtimeMs > webappStat.mtimeMs) {
|
|
93
|
+
try {
|
|
94
|
+
Bun.spawnSync(["jar", "xf", artifactInfo.path], { cwd: appWebappPath });
|
|
95
|
+
deployStep.update('WAR extraído');
|
|
96
|
+
} catch (e) {
|
|
97
|
+
// Fallback para extração com jar (funciona em todas as plataformas)
|
|
98
|
+
if (isWindows()) {
|
|
99
|
+
const extractCmd = `Expand-Archive -Path $env:ARTIFACT_PATH -DestinationPath $env:DEST_PATH -Force`;
|
|
100
|
+
Bun.spawnSync(["powershell", "-command", extractCmd], {
|
|
101
|
+
env: {
|
|
102
|
+
...process.env,
|
|
103
|
+
ARTIFACT_PATH: artifactInfo.path,
|
|
104
|
+
DEST_PATH: appWebappPath
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
} else {
|
|
108
|
+
// Linux/Mac: usa unzip ou jar
|
|
109
|
+
try {
|
|
110
|
+
Bun.spawnSync(["unzip", "-q", "-o", artifactInfo.path, "-d", appWebappPath]);
|
|
111
|
+
} catch {
|
|
112
|
+
// Fallback final para jar
|
|
113
|
+
Bun.spawnSync(getWarExtractCommand(artifactInfo.path, appWebappPath), {
|
|
114
|
+
cwd: appWebappPath
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
deployStep.update('WAR extraído (fallback)');
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
deployStep.update('Webapp já está atualizado');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
deployStep.success('Deploy preparado');
|
|
122
126
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
126
|
-
Logger.error(message);
|
|
127
|
-
throw error;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
127
|
+
this.injectContextConfiguration(appWebappPath);
|
|
128
|
+
this.injectHotswapProperties(appWebappPath);
|
|
130
129
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
Logger.config("debug", config.project.debug ? `port ${config.project.debugPort}` : false);
|
|
130
|
+
const finalAppUrl = `http://localhost:${config.tomcat.port}/${finalContextPath}`;
|
|
131
|
+
|
|
132
|
+
tomcat.onReady = async () => {
|
|
133
|
+
await this.handleServerReady(config, finalAppUrl, finalContextPath, tomcat, !!incremental);
|
|
134
|
+
};
|
|
137
135
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
136
|
+
const serverStep = operation.step('server', 'Iniciando Tomcat...');
|
|
137
|
+
tomcat.start(config, isWatching);
|
|
138
|
+
|
|
139
|
+
// O serverStep será concluído quando o Tomcat estiver pronto
|
|
140
|
+
// (via callback onReady)
|
|
141
|
+
|
|
142
|
+
} catch (error) {
|
|
143
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
144
|
+
this.logger.error(message);
|
|
145
|
+
operation.fail('Deploy falhou', error as Error);
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
147
149
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
Logger.endSection();
|
|
157
|
-
}
|
|
150
|
+
private logConfiguration(config: AppConfig, isWatching: boolean) {
|
|
151
|
+
this.logger.section("Configuração");
|
|
152
|
+
this.logger.config("runtime", config.project.buildTool.toLowerCase());
|
|
153
|
+
if (config.project.profile) this.logger.config("profile", config.project.profile);
|
|
154
|
+
this.logger.config("watch", isWatching);
|
|
155
|
+
this.logger.config("debug", config.project.debug ? `porta ${config.project.debugPort}` : false);
|
|
158
156
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
157
|
+
const javaVer = Bun.spawnSync([getJavaPath(), "-version"]);
|
|
158
|
+
const output = (javaVer.stderr.toString() + javaVer.stdout.toString()).toLowerCase();
|
|
159
|
+
const hasDcevm = ["dcevm", "jetbrains", "trava", "jbr"].some(v => output.includes(v));
|
|
160
|
+
|
|
161
|
+
if (!hasDcevm && isWatching) {
|
|
162
|
+
this.logger.config("hotswap", "padrão");
|
|
163
|
+
} else if (hasDcevm) {
|
|
164
|
+
this.logger.config("hotswap", "dcevm (avançado)");
|
|
165
|
+
}
|
|
162
166
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
+
const srcPath = path.join(process.cwd(), "src");
|
|
168
|
+
if (fs.existsSync(srcPath)) {
|
|
169
|
+
const contextPath = (config.project.appName || "").replace(".war", "");
|
|
170
|
+
const endpoints = EndpointService.scan(srcPath, contextPath);
|
|
171
|
+
if (endpoints.length > 0) {
|
|
172
|
+
this.logger.config("endpoints", endpoints.length);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
this.logger.newline();
|
|
176
|
+
}
|
|
167
177
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
178
|
+
private injectContextConfiguration(appPath: string) {
|
|
179
|
+
const metaInfPath = path.join(appPath, "META-INF");
|
|
180
|
+
if (!fs.existsSync(metaInfPath)) fs.mkdirSync(metaInfPath, { recursive: true });
|
|
172
181
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const xavvaProps = path.join(process.cwd(), ".xavva", "hotswap-agent.properties");
|
|
178
|
-
if (fs.existsSync(xavvaProps)) {
|
|
179
|
-
fs.copyFileSync(xavvaProps, path.join(webInfClassesDir, "hotswap-agent.properties"));
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
+
const contextPath = path.join(metaInfPath, "context.xml");
|
|
183
|
+
|
|
184
|
+
// Aumentamos o cache para 100MB (102400 KB) para evitar avisos de cache insuficiente
|
|
185
|
+
const contextContent = `<?xml version="1.0" encoding="UTF-8"?>\n<Context>\n <Resources cachingAllowed="true" cacheMaxSize="102400" />\n</Context>`;
|
|
182
186
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
Logger.ready("Server ready");
|
|
191
|
-
Logger.url("Local", url);
|
|
192
|
-
Logger.info("Status", `${response.status}`);
|
|
193
|
-
Logger.info("Memory", memory);
|
|
194
|
-
Logger.done();
|
|
187
|
+
try {
|
|
188
|
+
fs.writeFileSync(contextPath, contextContent);
|
|
189
|
+
this.logger.debug(`context.xml configurado em ${contextPath}`);
|
|
190
|
+
} catch (e) {
|
|
191
|
+
this.logger.warn(`Não foi possível configurar context.xml: ${(e as Error).message}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
195
194
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
Logger.warn(`App returned status ${response.status}`);
|
|
207
|
-
}
|
|
208
|
-
} catch (e) {
|
|
209
|
-
Logger.error(`Could not connect to ${url}`);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
195
|
+
private injectHotswapProperties(appWebappPath: string) {
|
|
196
|
+
const webInfClassesDir = path.join(appWebappPath, "WEB-INF", "classes");
|
|
197
|
+
if (!fs.existsSync(webInfClassesDir)) fs.mkdirSync(webInfClassesDir, { recursive: true });
|
|
198
|
+
|
|
199
|
+
const xavvaProps = path.join(process.cwd(), ".xavva", "hotswap-agent.properties");
|
|
200
|
+
if (fs.existsSync(xavvaProps)) {
|
|
201
|
+
fs.copyFileSync(xavvaProps, path.join(webInfClassesDir, "hotswap-agent.properties"));
|
|
202
|
+
this.logger.debug('hotswap-agent.properties copiado');
|
|
203
|
+
}
|
|
204
|
+
}
|
|
212
205
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
206
|
+
private async handleServerReady(config: AppConfig, url: string, context: string, tomcat: TomcatService, incremental: boolean) {
|
|
207
|
+
try {
|
|
208
|
+
await new Promise(r => setTimeout(r, 1500));
|
|
209
|
+
const response = await fetch(url);
|
|
210
|
+
if (response.status < 500) {
|
|
211
|
+
const memory = await tomcat.getMemoryUsage();
|
|
212
|
+
this.logger.divider();
|
|
213
|
+
this.logger.ready("Servidor pronto");
|
|
214
|
+
this.logger.url("Local", url);
|
|
215
|
+
this.logger.config("Status", response.status);
|
|
216
|
+
this.logger.config("Memória", memory);
|
|
217
|
+
this.logger.newline();
|
|
220
218
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
219
|
+
if (!config.project.quiet) {
|
|
220
|
+
this.showEndpointMap(config.tomcat.port, context);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (incremental) {
|
|
224
|
+
await BrowserService.reload(url);
|
|
225
|
+
} else {
|
|
226
|
+
BrowserService.open(url);
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
this.logger.warn(`Aplicação retornou status ${response.status}`);
|
|
230
|
+
}
|
|
231
|
+
} catch (e) {
|
|
232
|
+
this.logger.error(`Não foi possível conectar em ${url}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
225
235
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
236
|
+
private showEndpointMap(port: number, context: string) {
|
|
237
|
+
const endpoints = EndpointService.scan(path.join(process.cwd(), "src"), context);
|
|
238
|
+
if (endpoints.length > 0) {
|
|
239
|
+
this.logger.section("Endpoints");
|
|
240
|
+
|
|
241
|
+
const apis = endpoints.filter(e => e.className !== "JSP");
|
|
242
|
+
const jsps = endpoints.filter(e => e.className === "JSP");
|
|
234
243
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if (!appFolder && fs.existsSync(webappsPath)) {
|
|
241
|
-
const folders = fs.readdirSync(webappsPath, { withFileTypes: true })
|
|
242
|
-
.filter(dirent => dirent.isDirectory() && !["ROOT", "manager", "host-manager", "docs"].includes(dirent.name));
|
|
243
|
-
if (folders.length === 1) appFolder = folders[0].name;
|
|
244
|
-
}
|
|
244
|
+
if (apis.length > 0) {
|
|
245
|
+
this.logger.info("APIs:", "");
|
|
246
|
+
const uniqueApiUrls = [...new Set(apis.map(e => `http://localhost:${port}${e.fullPath}`))];
|
|
247
|
+
uniqueApiUrls.forEach(url => this.logger.info("", url));
|
|
248
|
+
}
|
|
245
249
|
|
|
246
|
-
|
|
247
|
-
|
|
250
|
+
if (jsps.length > 0) {
|
|
251
|
+
this.logger.info("JSPs:", "");
|
|
252
|
+
const uniqueJspUrls = [...new Set(jsps.map(e => `http://localhost:${port}${e.fullPath}`))];
|
|
253
|
+
uniqueJspUrls.forEach(url => this.logger.info("", ` ${url}`));
|
|
254
|
+
}
|
|
255
|
+
this.logger.newline();
|
|
256
|
+
}
|
|
257
|
+
}
|
|
248
258
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const targetDir = path.dirname(targetPath);
|
|
260
|
-
if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true });
|
|
259
|
+
async syncResource(config: AppConfig, filename: string): Promise<void> {
|
|
260
|
+
const contextPath = (config.project.appName || "").replace(".war", "");
|
|
261
|
+
const webappsPath = path.join(config.tomcat.path, "webapps");
|
|
262
|
+
let appFolder = contextPath;
|
|
263
|
+
|
|
264
|
+
if (!appFolder && fs.existsSync(webappsPath)) {
|
|
265
|
+
const folders = fs.readdirSync(webappsPath, { withFileTypes: true })
|
|
266
|
+
.filter(dirent => dirent.isDirectory() && !["ROOT", "manager", "host-manager", "docs"].includes(dirent.name));
|
|
267
|
+
if (folders.length === 1) appFolder = folders[0].name;
|
|
268
|
+
}
|
|
261
269
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
270
|
+
const explodedPath = path.join(webappsPath, appFolder);
|
|
271
|
+
if (!appFolder || !fs.existsSync(explodedPath)) return;
|
|
272
|
+
|
|
273
|
+
const parts = filename.split(/[/\\]/);
|
|
274
|
+
const webappIndex = parts.indexOf("webapp");
|
|
275
|
+
const webContentIndex = parts.indexOf("WebContent");
|
|
276
|
+
const rootIndex = webappIndex !== -1 ? webappIndex : webContentIndex;
|
|
277
|
+
|
|
278
|
+
if (rootIndex !== -1) {
|
|
279
|
+
const relPath = parts.slice(rootIndex + 1).join(path.sep);
|
|
280
|
+
const targetPath = path.join(explodedPath, relPath);
|
|
281
|
+
|
|
282
|
+
try {
|
|
283
|
+
const targetDir = path.dirname(targetPath);
|
|
284
|
+
if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true });
|
|
285
|
+
|
|
286
|
+
fs.copyFileSync(filename, targetPath);
|
|
287
|
+
this.logger.file(path.basename(filename), 'synced');
|
|
288
|
+
|
|
289
|
+
const appUrl = `http://localhost:${config.tomcat.port}/${appFolder}`;
|
|
290
|
+
await BrowserService.reload(appUrl);
|
|
291
|
+
} catch (e) {
|
|
292
|
+
this.logger.error(`Falha ao sincronizar: ${filename}`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
273
296
|
}
|