@archznn/xavva 2.6.0 → 2.7.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.
@@ -0,0 +1,183 @@
1
+ /**
2
+ * DeployWatcher - Específico para watch de deploy
3
+ * Usa FileWatcher genérico e adiciona lógica de deploy
4
+ */
5
+
6
+ import { FileWatcher, type FileChangeEvent } from "./FileWatcher";
7
+ import { DeployCommand } from "../commands/DeployCommand";
8
+ import { Logger } from "../utils/ui";
9
+ import type { AppConfig } from "../types/config";
10
+ import { WATCHER_DEBOUNCE_MS, WATCHER_COOLING_MS } from "../utils/constants";
11
+
12
+ export class DeployWatcher {
13
+ private fileWatcher: FileWatcher;
14
+ private isDeploying = false;
15
+ private pendingFullBuild = false;
16
+ private modifiedFiles = new Set<string>();
17
+ private pendingFiles = new Set<string>();
18
+ private hasPendingChanges = false;
19
+
20
+ constructor(
21
+ private config: AppConfig,
22
+ private deployCmd: DeployCommand
23
+ ) {
24
+ this.fileWatcher = new FileWatcher({
25
+ recursive: true,
26
+ debounceMs: WATCHER_DEBOUNCE_MS,
27
+ coolingMs: WATCHER_COOLING_MS,
28
+ });
29
+ }
30
+
31
+ /**
32
+ * Inicia o watch de deploy
33
+ */
34
+ async start(): Promise<void> {
35
+ // Executa deploy inicial
36
+ await this.run(false);
37
+
38
+ // Configura handlers
39
+ this.setupHandlers();
40
+
41
+ // Inicia o watcher
42
+ this.fileWatcher.start();
43
+
44
+ Logger.info("DeployWatcher", "Monitorando alterações...");
45
+ }
46
+
47
+ /**
48
+ * Para o watching
49
+ */
50
+ stop(): void {
51
+ this.fileWatcher.stop();
52
+ }
53
+
54
+ /**
55
+ * Configura handlers para diferentes tipos de arquivos
56
+ */
57
+ private setupHandlers(): void {
58
+ // Handler para configurações de build
59
+ this.fileWatcher.on(/(pom\.xml|build\.gradle|build\.gradle\.kts)$/, (event) => {
60
+ this.handleBuildConfigChange(event);
61
+ });
62
+
63
+ // Handler para arquivos Java
64
+ this.fileWatcher.on(/\.java$/, (event) => {
65
+ this.handleJavaChange(event);
66
+ });
67
+
68
+ // Handler para recursos estáticos (JSP, HTML, CSS, etc)
69
+ this.fileWatcher.on(/\.(jsp|html|css|js|xml|properties)$/, (event) => {
70
+ this.handleResourceChange(event);
71
+ });
72
+ }
73
+
74
+ /**
75
+ * Trata mudança em arquivo de configuração de build
76
+ */
77
+ private async handleBuildConfigChange(event: FileChangeEvent): Promise<void> {
78
+ if (!event.filename) return;
79
+
80
+ Logger.watcher(`Build configuration changed: ${event.filename}`, 'warn');
81
+
82
+ // Limpa cache quando config muda
83
+ const { BuildCacheService } = await import("./BuildCacheService");
84
+ new BuildCacheService().clearCache();
85
+
86
+ this.pendingFullBuild = true;
87
+ }
88
+
89
+ /**
90
+ * Trata mudança em arquivo Java
91
+ */
92
+ private handleJavaChange(event: FileChangeEvent): void {
93
+ if (!event.filename || this.isDeploying) {
94
+ if (event.filename) {
95
+ this.pendingFiles.add(event.filename);
96
+ this.hasPendingChanges = true;
97
+ }
98
+ return;
99
+ }
100
+
101
+ Logger.watcher(event.filename, 'watch');
102
+ this.modifiedFiles.add(event.filename);
103
+
104
+ // Debounce para acumular múltiplas mudanças
105
+ this.scheduleDeploy();
106
+ }
107
+
108
+ /**
109
+ * Trata mudança em recurso estático
110
+ */
111
+ private async handleResourceChange(event: FileChangeEvent): Promise<void> {
112
+ if (!event.filename) return;
113
+
114
+ Logger.watcher(event.filename, 'resource');
115
+
116
+ try {
117
+ await this.deployCmd.syncResource(this.config, event.filename);
118
+ } catch (error) {
119
+ Logger.error(`Falha ao sincronizar recurso: ${event.filename}`);
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Agenda deploy após debounce
125
+ */
126
+ private scheduleDeploy(): void {
127
+ // O debounce já é feito pelo FileWatcher
128
+ // Aqui apenas executamos o deploy
129
+ const filesToCompile = [...this.modifiedFiles];
130
+ this.modifiedFiles.clear();
131
+
132
+ this.run(this.pendingFullBuild ? false : true, filesToCompile);
133
+ this.pendingFullBuild = false;
134
+ }
135
+
136
+ /**
137
+ * Executa o deploy
138
+ */
139
+ private async run(incremental = false, changedFiles?: string[]): Promise<void> {
140
+ if (this.isDeploying) return;
141
+
142
+ this.isDeploying = true;
143
+
144
+ try {
145
+ await this.deployCmd.execute(this.config, {
146
+ watch: true,
147
+ incremental,
148
+ changedFiles,
149
+ });
150
+ } catch (error) {
151
+ // Erro já é tratado pelo comando
152
+ } finally {
153
+ this.isDeploying = false;
154
+
155
+ // Processa mudanças pendentes
156
+ if (this.hasPendingChanges) {
157
+ const pending = [...this.pendingFiles];
158
+ this.pendingFiles.clear();
159
+ this.hasPendingChanges = false;
160
+
161
+ Logger.watcher(`Processing ${pending.length} pending change(s)...`, 'warn');
162
+
163
+ setTimeout(() => {
164
+ this.run(true, pending);
165
+ }, 100);
166
+ }
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Verifica se é arquivo de recurso (não Java)
172
+ */
173
+ static isResourceFile(filename: string): boolean {
174
+ return /\.(jsp|html|css|js|xml|properties)$/.test(filename);
175
+ }
176
+
177
+ /**
178
+ * Verifica se é arquivo de configuração de build
179
+ */
180
+ static isBuildConfig(filename: string): boolean {
181
+ return /^(pom\.xml|build\.gradle|build\.gradle\.kts)$/.test(filename);
182
+ }
183
+ }
@@ -1,4 +1,5 @@
1
1
  import { Logger } from "../utils/ui";
2
+ import { VERSIONS, getAvailableTomcatVersions, isSupportedTomcatVersion } from "../config/versions";
2
3
  import {
3
4
  existsSync,
4
5
  mkdirSync,
@@ -45,25 +46,10 @@ export class EmbeddedTomcatService {
45
46
  private downloadUrl: string;
46
47
  private isInstalled: boolean = false;
47
48
 
48
- // Versões estáveis do Tomcat (atualizadas: 2026-03-04)
49
- // URLs são construídas dinamicamente baseadas na plataforma
50
- private static readonly VERSIONS: Record<
51
- string,
52
- { sha512: string }
53
- > = {
54
- "10.1.52": {
55
- sha512: "",
56
- },
57
- "9.0.115": {
58
- sha512: "",
59
- },
60
- "11.0.18": {
61
- sha512: "",
62
- },
63
- };
49
+ // Versões agora centralizadas em src/config/versions.ts
64
50
 
65
51
  constructor(options: EmbeddedTomcatOptions) {
66
- this.version = options.version || "10.1.52";
52
+ this.version = options.version || VERSIONS.TOMCAT.DEFAULT;
67
53
  this.port = options.port || 8080;
68
54
  this.webappPath = path.resolve(options.webappPath);
69
55
  this.contextPath = options.contextPath || "/";
@@ -71,7 +57,7 @@ export class EmbeddedTomcatService {
71
57
  this.tomcatHome = path.join(this.baseDir, this.version);
72
58
 
73
59
  // Constrói URL de download baseada na plataforma
74
- const versionInfo = EmbeddedTomcatService.VERSIONS[this.version];
60
+ const versionInfo = isSupportedTomcatVersion(this.version) ? { sha512: "" } : null;
75
61
  if (versionInfo) {
76
62
  // Usa URL primária (CDN Apache)
77
63
  this.downloadUrl = getTomcatDownloadUrl(this.version);
@@ -354,7 +340,7 @@ export class EmbeddedTomcatService {
354
340
  * Lista versões disponíveis
355
341
  */
356
342
  static getAvailableVersions(): string[] {
357
- return Object.keys(EmbeddedTomcatService.VERSIONS);
343
+ return getAvailableTomcatVersions();
358
344
  }
359
345
 
360
346
  /**