@archznn/xavva 2.6.0 → 2.8.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.
@@ -1,4 +1,6 @@
1
1
  import { Logger } from "../utils/ui";
2
+ import { ProgressBar, ThemedSpinner } from "../utils/ProgressBar";
3
+ import { VERSIONS, getAvailableTomcatVersions, isSupportedTomcatVersion } from "../config/versions";
2
4
  import {
3
5
  existsSync,
4
6
  mkdirSync,
@@ -45,25 +47,10 @@ export class EmbeddedTomcatService {
45
47
  private downloadUrl: string;
46
48
  private isInstalled: boolean = false;
47
49
 
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
- };
50
+ // Versões agora centralizadas em src/config/versions.ts
64
51
 
65
52
  constructor(options: EmbeddedTomcatOptions) {
66
- this.version = options.version || "10.1.52";
53
+ this.version = options.version || VERSIONS.TOMCAT.DEFAULT;
67
54
  this.port = options.port || 8080;
68
55
  this.webappPath = path.resolve(options.webappPath);
69
56
  this.contextPath = options.contextPath || "/";
@@ -71,7 +58,7 @@ export class EmbeddedTomcatService {
71
58
  this.tomcatHome = path.join(this.baseDir, this.version);
72
59
 
73
60
  // Constrói URL de download baseada na plataforma
74
- const versionInfo = EmbeddedTomcatService.VERSIONS[this.version];
61
+ const versionInfo = isSupportedTomcatVersion(this.version) ? { sha512: "" } : null;
75
62
  if (versionInfo) {
76
63
  // Usa URL primária (CDN Apache)
77
64
  this.downloadUrl = getTomcatDownloadUrl(this.version);
@@ -354,34 +341,76 @@ export class EmbeddedTomcatService {
354
341
  * Lista versões disponíveis
355
342
  */
356
343
  static getAvailableVersions(): string[] {
357
- return Object.keys(EmbeddedTomcatService.VERSIONS);
344
+ return getAvailableTomcatVersions();
358
345
  }
359
346
 
360
347
  /**
361
348
  * Download com progresso
362
349
  */
363
350
  private async downloadFile(url: string, destPath: string): Promise<void> {
364
- const spinner = Logger.spinner(`Baixando Tomcat ${this.version}...`);
351
+ const response = await fetch(url);
365
352
 
366
- try {
367
- const response = await fetch(url);
353
+ if (!response.ok) {
354
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
355
+ }
368
356
 
369
- if (!response.ok) {
370
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
357
+ const totalSize = parseInt(response.headers.get("content-length") || "0");
358
+
359
+ // Se temos content-length, usar progress bar
360
+ if (totalSize > 0) {
361
+ const progress = new ProgressBar({
362
+ title: `Baixando Tomcat ${this.version}`,
363
+ total: totalSize,
364
+ width: 25
365
+ });
366
+
367
+ const reader = response.body?.getReader();
368
+ if (!reader) {
369
+ throw new Error("Response body não disponível");
371
370
  }
372
371
 
373
- const totalSize = parseInt(response.headers.get("content-length") || "0");
374
- const buffer = await response.arrayBuffer();
372
+ const chunks: Uint8Array[] = [];
373
+ let received = 0;
374
+
375
+ while (true) {
376
+ const { done, value } = await reader.read();
377
+ if (done) break;
378
+
379
+ chunks.push(value);
380
+ received += value.length;
381
+ progress.update(received);
382
+ }
375
383
 
376
- writeFileSync(destPath, Buffer.from(buffer));
384
+ progress.complete();
377
385
 
378
- spinner(true);
386
+ // Concatena chunks e salva
387
+ const allChunks = new Uint8Array(received);
388
+ let position = 0;
389
+ for (const chunk of chunks) {
390
+ allChunks.set(chunk, position);
391
+ position += chunk.length;
392
+ }
379
393
 
380
- const sizeMB = (buffer.byteLength / 1024 / 1024).toFixed(1);
394
+ await fsPromises.writeFile(destPath, allChunks);
395
+
396
+ const sizeMB = (received / 1024 / 1024).toFixed(1);
381
397
  Logger.info("Download", `${sizeMB} MB baixados`);
382
- } catch (error) {
383
- spinner(false);
384
- throw error;
398
+ } else {
399
+ // Sem content-length, usar spinner temático
400
+ const spinner = new ThemedSpinner();
401
+ const stop = spinner.start(`Baixando Tomcat ${this.version}`, "dots", "download");
402
+
403
+ try {
404
+ const buffer = await response.arrayBuffer();
405
+ await fsPromises.writeFile(destPath, Buffer.from(buffer));
406
+ stop(true);
407
+
408
+ const sizeMB = (buffer.byteLength / 1024 / 1024).toFixed(1);
409
+ Logger.info("Download", `${sizeMB} MB baixados`);
410
+ } catch (error) {
411
+ stop(false);
412
+ throw error;
413
+ }
385
414
  }
386
415
  }
387
416
 
@@ -389,13 +418,14 @@ export class EmbeddedTomcatService {
389
418
  * Extrai arquivo de arquivos (ZIP ou tar.gz)
390
419
  */
391
420
  private async extractZip(zipPath: string, destDir: string): Promise<void> {
392
- const spinner = Logger.spinner("Extraindo arquivos...");
421
+ const spinner = new ThemedSpinner();
422
+ const stop = spinner.start("Extraindo arquivos", "pulse", "build");
393
423
 
394
424
  return new Promise((resolve, reject) => {
395
425
  const cmd = getExtractCommand(zipPath, destDir);
396
426
 
397
427
  if (!cmd) {
398
- spinner(false);
428
+ stop(false);
399
429
  reject(new Error(`Formato de arquivo não suportado: ${path.extname(zipPath)}`));
400
430
  return;
401
431
  }
@@ -404,16 +434,16 @@ export class EmbeddedTomcatService {
404
434
 
405
435
  extractProcess.on("close", (code) => {
406
436
  if (code === 0) {
407
- spinner(true);
437
+ stop(true);
408
438
  resolve();
409
439
  } else {
410
- spinner(false);
440
+ stop(false);
411
441
  reject(new Error(`Falha ao extrair (código ${code})`));
412
442
  }
413
443
  });
414
444
 
415
445
  extractProcess.on("error", (err) => {
416
- spinner(false);
446
+ stop(false);
417
447
  reject(err);
418
448
  });
419
449
  });