versacompiler 2.0.2 → 2.0.3
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/dist/compiler/compile.js +744 -111
- package/dist/compiler/module-resolution-optimizer.js +3 -4
- package/dist/compiler/typescript-error-parser.js +1 -1
- package/dist/compiler/typescript-sync-validator.js +1 -1
- package/dist/compiler/typescript-worker-pool.js +13 -16
- package/dist/compiler/typescript-worker-thread.cjs +1 -2
- package/dist/hrm/getInstanciaVue.js +1 -1
- package/dist/hrm/initHRM.js +1 -1
- package/dist/main.js +64 -17
- package/dist/servicios/browserSync.js +1 -1
- package/dist/servicios/file-watcher.js +16 -4
- package/dist/servicios/logger.js +36 -7
- package/dist/servicios/readConfig.js +1 -1
- package/dist/utils/module-resolver.js +3 -4
- package/package.json +1 -1
package/dist/compiler/compile.js
CHANGED
|
@@ -2,11 +2,13 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import { glob, mkdir, readFile, stat, unlink, writeFile, } from 'node:fs/promises';
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import { argv, cwd, env
|
|
5
|
+
import process, { argv, cwd, env } from 'node:process';
|
|
6
6
|
// Lazy loading optimizations - Only import lightweight modules synchronously
|
|
7
|
-
import { logger } from '../servicios/logger.js';
|
|
7
|
+
import { logger, setProgressManagerGetter } from '../servicios/logger.js';
|
|
8
8
|
import { promptUser } from '../utils/promptUser.js';
|
|
9
9
|
import { showTimingForHumans } from '../utils/utils.js';
|
|
10
|
+
// Configurar el getter del ProgressManager para el logger
|
|
11
|
+
setProgressManagerGetter(() => ProgressManager.getInstance());
|
|
10
12
|
// Heavy dependencies will be loaded dynamically when needed
|
|
11
13
|
let chalk;
|
|
12
14
|
let ESLint;
|
|
@@ -355,8 +357,8 @@ const COMPILATION_ENV_VARS = [
|
|
|
355
357
|
];
|
|
356
358
|
class SmartCompilationCache {
|
|
357
359
|
cache = new Map();
|
|
358
|
-
maxEntries =
|
|
359
|
-
maxMemory =
|
|
360
|
+
maxEntries = 200; // Reducido para tests de estrés
|
|
361
|
+
maxMemory = 50 * 1024 * 1024; // 50MB límite (reducido)
|
|
360
362
|
currentMemoryUsage = 0;
|
|
361
363
|
// ✨ ISSUE #3: Sistema de vigilancia de dependencias
|
|
362
364
|
fileWatchers = new Map(); // chokidar watchers
|
|
@@ -580,22 +582,31 @@ class SmartCompilationCache {
|
|
|
580
582
|
// Si hay error, no cachear
|
|
581
583
|
console.warn(`Warning: No se pudo cachear ${filePath}:`, error);
|
|
582
584
|
}
|
|
583
|
-
}
|
|
584
|
-
/**
|
|
585
|
+
} /**
|
|
585
586
|
* Aplica política LRU para liberar espacio
|
|
586
587
|
*/
|
|
587
588
|
evictIfNeeded(newEntrySize) {
|
|
588
|
-
// Verificar límite de entradas
|
|
589
|
-
while (this.cache.size >= this.maxEntries) {
|
|
589
|
+
// Verificar límite de entradas más agresivamente
|
|
590
|
+
while (this.cache.size >= this.maxEntries * 0.8) {
|
|
591
|
+
// Limpiar cuando llegue al 80%
|
|
590
592
|
this.evictLRU();
|
|
591
593
|
}
|
|
592
|
-
// Verificar límite de memoria
|
|
593
|
-
while (this.currentMemoryUsage + newEntrySize > this.maxMemory &&
|
|
594
|
+
// Verificar límite de memoria más agresivamente
|
|
595
|
+
while (this.currentMemoryUsage + newEntrySize > this.maxMemory * 0.8 && // Limpiar cuando llegue al 80%
|
|
594
596
|
this.cache.size > 0) {
|
|
595
597
|
this.evictLRU();
|
|
596
598
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
+
// Eviction adicional si la memoria total del proceso es alta
|
|
600
|
+
const memUsage = process.memoryUsage();
|
|
601
|
+
const heapUsedMB = memUsage.heapUsed / (1024 * 1024);
|
|
602
|
+
if (heapUsedMB > 200 && this.cache.size > 50) {
|
|
603
|
+
// Si heap > 200MB, limpiar más agresivamente
|
|
604
|
+
const entriesToRemove = Math.min(this.cache.size - 50, 10);
|
|
605
|
+
for (let i = 0; i < entriesToRemove; i++) {
|
|
606
|
+
this.evictLRU();
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
} /**
|
|
599
610
|
* Elimina la entrada menos recientemente usada
|
|
600
611
|
*/
|
|
601
612
|
evictLRU() {
|
|
@@ -615,6 +626,23 @@ class SmartCompilationCache {
|
|
|
615
626
|
}
|
|
616
627
|
}
|
|
617
628
|
}
|
|
629
|
+
/**
|
|
630
|
+
* Método público para limpiar entradas del cache cuando sea necesario
|
|
631
|
+
*/
|
|
632
|
+
cleanOldEntries(maxEntriesToRemove = 20) {
|
|
633
|
+
let removedCount = 0;
|
|
634
|
+
for (let i = 0; i < maxEntriesToRemove && this.cache.size > 0; i++) {
|
|
635
|
+
const sizeBefore = this.cache.size;
|
|
636
|
+
this.evictLRU();
|
|
637
|
+
if (this.cache.size < sizeBefore) {
|
|
638
|
+
removedCount++;
|
|
639
|
+
}
|
|
640
|
+
else {
|
|
641
|
+
break; // No se pudo remover más entradas
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
return removedCount;
|
|
645
|
+
}
|
|
618
646
|
/**
|
|
619
647
|
* Carga el cache desde disco
|
|
620
648
|
*/
|
|
@@ -711,7 +739,7 @@ class SmartCompilationCache {
|
|
|
711
739
|
persistent: false,
|
|
712
740
|
ignoreInitial: true,
|
|
713
741
|
depth: 1, // Solo primer nivel para performance
|
|
714
|
-
ignored: /(^|[
|
|
742
|
+
ignored: /(^|[/\\])\../, // Ignorar archivos ocultos
|
|
715
743
|
});
|
|
716
744
|
nodeModulesWatcher.on('addDir', (path) => {
|
|
717
745
|
logger.info(`📦 Nueva dependencia instalada: ${path.split(/[/\\]/).pop()}`);
|
|
@@ -952,28 +980,42 @@ function clearCompilationState() {
|
|
|
952
980
|
/**
|
|
953
981
|
* Muestra un resumen detallado de todos los errores de compilación
|
|
954
982
|
*/
|
|
955
|
-
async function displayCompilationSummary(isVerbose = false) {
|
|
983
|
+
async function displayCompilationSummary(isVerbose = false, totalTime) {
|
|
956
984
|
const chalk = await loadChalk();
|
|
957
985
|
if (compilationErrors.length === 0 && compilationResults.length === 0) {
|
|
958
986
|
logger.info(chalk.green('✅ No hay errores de compilación para mostrar.'));
|
|
987
|
+
if (totalTime) {
|
|
988
|
+
logger.info(chalk.bold(`\n⏱️ TIEMPO TOTAL DE COMPILACIÓN: ${totalTime}`));
|
|
989
|
+
}
|
|
959
990
|
return;
|
|
960
991
|
}
|
|
961
|
-
|
|
962
|
-
|
|
992
|
+
// 🎨 Header moderno del resumen
|
|
993
|
+
const summaryLine = '━'.repeat(40);
|
|
994
|
+
logger.info('');
|
|
995
|
+
logger.info(chalk.bold.cyan('📊 Resumen de Compilación'));
|
|
996
|
+
logger.info(chalk.gray(summaryLine)); // ⏱️ Tiempo total con formato elegante
|
|
997
|
+
if (totalTime) {
|
|
998
|
+
logger.info(chalk.bold(`⏱️ Tiempo Total: ${chalk.green(totalTime)}`));
|
|
999
|
+
logger.info('');
|
|
1000
|
+
} // 🔧 Estadísticas por etapa con mejor formato
|
|
963
1001
|
if (compilationResults.length > 0) {
|
|
964
|
-
logger.info(chalk.blue('
|
|
1002
|
+
logger.info(chalk.bold.blue('🔧 Estadísticas por Etapa:'));
|
|
965
1003
|
for (const result of compilationResults) {
|
|
966
1004
|
const totalFiles = result.success + result.errors;
|
|
967
1005
|
const successRate = totalFiles > 0
|
|
968
1006
|
? Math.round((result.success / totalFiles) * 100)
|
|
969
1007
|
: 0;
|
|
970
|
-
|
|
971
|
-
const
|
|
972
|
-
const
|
|
973
|
-
const
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
logger.info(
|
|
1008
|
+
// Iconos y colores dinámicos por etapa
|
|
1009
|
+
const stageIcon = getStageIcon(result.stage);
|
|
1010
|
+
const statusColor = result.errors === 0 ? chalk.green : chalk.red;
|
|
1011
|
+
const progressBar = createProgressBarWithPercentage(successRate, 20);
|
|
1012
|
+
logger.info(` ${stageIcon} ${chalk.bold(result.stage)}`);
|
|
1013
|
+
logger.info(` ${statusColor('●')} ${result.success}/${totalFiles} archivos ${statusColor(`(${successRate}%)`)}`);
|
|
1014
|
+
logger.info(` ${progressBar}`);
|
|
1015
|
+
if (result.errors > 0) {
|
|
1016
|
+
logger.info(` ${chalk.red('⚠')} ${result.errors} ${result.errors === 1 ? 'error' : 'errores'}`);
|
|
1017
|
+
}
|
|
1018
|
+
logger.info('');
|
|
977
1019
|
}
|
|
978
1020
|
}
|
|
979
1021
|
// Mostrar errores detallados
|
|
@@ -1014,33 +1056,60 @@ async function displayCompilationSummary(isVerbose = false) {
|
|
|
1014
1056
|
}
|
|
1015
1057
|
}
|
|
1016
1058
|
fileIndex++;
|
|
1017
|
-
}
|
|
1018
|
-
// Mostrar totales finales
|
|
1059
|
+
} // 📊 Mostrar totales finales con diseño moderno
|
|
1019
1060
|
const totalErrors = compilationErrors.filter(e => e.severity === 'error').length;
|
|
1020
1061
|
const totalWarnings = compilationErrors.filter(e => e.severity === 'warning').length;
|
|
1021
1062
|
const totalFiles = errorsByFile.size;
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
logger.info(
|
|
1025
|
-
logger.info(
|
|
1063
|
+
// Header elegante para estadísticas finales
|
|
1064
|
+
const statLine = '═'.repeat(50);
|
|
1065
|
+
logger.info('');
|
|
1066
|
+
logger.info(chalk.bold.cyan(statLine));
|
|
1067
|
+
logger.info(chalk.bold.cyan(' 📊 RESUMEN FINAL'));
|
|
1068
|
+
logger.info(chalk.bold.cyan(statLine));
|
|
1069
|
+
// Estadísticas con iconos y colores modernos
|
|
1070
|
+
logger.info('');
|
|
1071
|
+
logger.info(chalk.bold('🎯 Resultados:'));
|
|
1072
|
+
logger.info(` 📁 Archivos afectados: ${chalk.cyan.bold(totalFiles)}`);
|
|
1073
|
+
logger.info(` ${totalErrors > 0 ? chalk.red('●') : chalk.green('○')} Errores: ${totalErrors > 0 ? chalk.red.bold(totalErrors) : chalk.green.bold('0')}`);
|
|
1074
|
+
logger.info(` ${totalWarnings > 0 ? chalk.yellow('●') : chalk.green('○')} Advertencias: ${totalWarnings > 0 ? chalk.yellow.bold(totalWarnings) : chalk.green.bold('0')}`);
|
|
1075
|
+
logger.info('');
|
|
1076
|
+
// Estado final con diseño visual atractivo
|
|
1026
1077
|
if (totalErrors > 0) {
|
|
1027
|
-
logger.info(chalk.red('🚨
|
|
1078
|
+
logger.info(chalk.red.bold('🚨 COMPILACIÓN COMPLETADA CON ERRORES'));
|
|
1079
|
+
logger.info(chalk.red(' Por favor revisa y corrige los problemas anteriores.'));
|
|
1080
|
+
}
|
|
1081
|
+
else if (totalWarnings > 0) {
|
|
1082
|
+
logger.info(chalk.yellow.bold('⚠️ COMPILACIÓN COMPLETADA CON ADVERTENCIAS'));
|
|
1083
|
+
logger.info(chalk.yellow(' Considera revisar las advertencias anteriores.'));
|
|
1028
1084
|
}
|
|
1029
1085
|
else {
|
|
1030
|
-
logger.info(chalk.
|
|
1086
|
+
logger.info(chalk.green.bold('✅ COMPILACIÓN EXITOSA'));
|
|
1087
|
+
logger.info(chalk.green(' ¡Todos los archivos se compilaron sin problemas!'));
|
|
1031
1088
|
}
|
|
1089
|
+
logger.info('');
|
|
1090
|
+
logger.info(chalk.bold.cyan(statLine));
|
|
1032
1091
|
}
|
|
1033
1092
|
else {
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1093
|
+
// Caso exitoso sin errores
|
|
1094
|
+
const successLine = '═'.repeat(50);
|
|
1095
|
+
logger.info('');
|
|
1096
|
+
logger.info(chalk.bold.green(successLine));
|
|
1097
|
+
logger.info(chalk.bold.green(' ✨ ÉXITO'));
|
|
1098
|
+
logger.info(chalk.bold.green(successLine));
|
|
1099
|
+
logger.info('');
|
|
1100
|
+
logger.info(chalk.green.bold('🎉 COMPILACIÓN COMPLETADA EXITOSAMENTE'));
|
|
1101
|
+
logger.info(chalk.green(' ¡No se encontraron errores ni advertencias!'));
|
|
1102
|
+
logger.info('');
|
|
1103
|
+
logger.info(chalk.bold.green(successLine));
|
|
1104
|
+
}
|
|
1105
|
+
logger.info('');
|
|
1037
1106
|
}
|
|
1038
1107
|
/**
|
|
1039
|
-
* Muestra errores del linter
|
|
1108
|
+
* Muestra errores del linter con formato visual moderno y profesional
|
|
1040
1109
|
*/
|
|
1041
1110
|
async function displayLinterErrors(errors) {
|
|
1042
1111
|
const chalk = await loadChalk();
|
|
1043
|
-
|
|
1112
|
+
// Agrupar errores por archivo
|
|
1044
1113
|
const errorsByFile = new Map();
|
|
1045
1114
|
errors.forEach(error => {
|
|
1046
1115
|
if (!errorsByFile.has(error.file)) {
|
|
@@ -1051,19 +1120,225 @@ async function displayLinterErrors(errors) {
|
|
|
1051
1120
|
const totalErrors = errors.filter(e => e.severity === 'error').length;
|
|
1052
1121
|
const totalWarnings = errors.filter(e => e.severity === 'warning').length;
|
|
1053
1122
|
const totalFiles = errorsByFile.size;
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1123
|
+
// Header estilo moderno con gradiente visual
|
|
1124
|
+
logger.info(chalk.bold.rgb(255, 120, 120)('╭─────────────────────────────────────────────────────────────╮'));
|
|
1125
|
+
logger.info(chalk.bold.rgb(255, 120, 120)('│ ') +
|
|
1126
|
+
chalk.bold.white('🔍 LINTER REPORT') +
|
|
1127
|
+
chalk.bold.rgb(255, 120, 120)(' │'));
|
|
1128
|
+
logger.info(chalk.bold.rgb(255, 120, 120)('╰─────────────────────────────────────────────────────────────╯'));
|
|
1129
|
+
// Resumen con iconos profesionales
|
|
1130
|
+
const errorIcon = totalErrors > 0 ? chalk.red('●') : chalk.green('○');
|
|
1131
|
+
const warningIcon = totalWarnings > 0 ? chalk.yellow('●') : chalk.green('○');
|
|
1132
|
+
logger.info('');
|
|
1133
|
+
logger.info(chalk.bold('📊 Summary:'));
|
|
1134
|
+
logger.info(` ${errorIcon} ${chalk.bold(totalErrors)} ${chalk.red('errors')}`);
|
|
1135
|
+
logger.info(` ${warningIcon} ${chalk.bold(totalWarnings)} ${chalk.yellow('warnings')}`);
|
|
1136
|
+
logger.info(` 📁 ${chalk.bold(totalFiles)} ${chalk.cyan('files')}`);
|
|
1137
|
+
logger.info('');
|
|
1138
|
+
if (totalErrors === 0 && totalWarnings === 0) {
|
|
1139
|
+
logger.info(chalk.green.bold('✨ All checks passed! No issues found.'));
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
// Mostrar errores por archivo con formato elegante
|
|
1143
|
+
let fileIndex = 1;
|
|
1144
|
+
for (const [filePath, fileErrors] of errorsByFile) {
|
|
1145
|
+
await displayFileErrorsGroup(filePath, fileErrors, fileIndex, totalFiles);
|
|
1146
|
+
fileIndex++;
|
|
1147
|
+
if (fileIndex <= totalFiles) {
|
|
1148
|
+
logger.info(chalk.gray('─'.repeat(80))); // Separador entre archivos
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
// Footer con estadísticas
|
|
1152
|
+
logger.info('');
|
|
1153
|
+
logger.info(chalk.bold.rgb(255, 120, 120)('╭─────────────────────────────────────────────────────────────╮'));
|
|
1154
|
+
logger.info(chalk.bold.rgb(255, 120, 120)('│ ') +
|
|
1155
|
+
chalk.bold.white(`Found ${totalErrors + totalWarnings} issues in ${totalFiles} files`) +
|
|
1156
|
+
' '.repeat(Math.max(0, 52 -
|
|
1157
|
+
`Found ${totalErrors + totalWarnings} issues in ${totalFiles} files`
|
|
1158
|
+
.length)) +
|
|
1159
|
+
chalk.bold.rgb(255, 120, 120)(' │'));
|
|
1160
|
+
logger.info(chalk.bold.rgb(255, 120, 120)('╰─────────────────────────────────────────────────────────────╯'));
|
|
1161
|
+
}
|
|
1162
|
+
/**
|
|
1163
|
+
* Muestra un grupo de errores para un archivo específico con formato moderno
|
|
1164
|
+
*/
|
|
1165
|
+
async function displayFileErrorsGroup(filePath, fileErrors, _fileIndex, _totalFiles) {
|
|
1166
|
+
const chalk = await loadChalk();
|
|
1167
|
+
// Header del archivo con iconos de estado
|
|
1168
|
+
const errorCount = fileErrors.filter(e => e.severity === 'error').length;
|
|
1169
|
+
const warningCount = fileErrors.filter(e => e.severity === 'warning').length;
|
|
1170
|
+
const statusIcon = errorCount > 0 ? chalk.red('✕') : chalk.yellow('⚠');
|
|
1171
|
+
const fileIcon = filePath.endsWith('.vue')
|
|
1172
|
+
? '🎨'
|
|
1173
|
+
: filePath.endsWith('.ts')
|
|
1174
|
+
? '📘'
|
|
1175
|
+
: filePath.endsWith('.js')
|
|
1176
|
+
? '📜'
|
|
1177
|
+
: '📄';
|
|
1178
|
+
logger.info('');
|
|
1179
|
+
logger.info(chalk.bold(`${statusIcon} ${fileIcon} ${chalk.cyan(path.relative(process.cwd(), filePath))}`));
|
|
1180
|
+
logger.info(chalk.gray(` ${errorCount} errors, ${warningCount} warnings`));
|
|
1181
|
+
logger.info('');
|
|
1182
|
+
// Mostrar cada error con formato elegante
|
|
1183
|
+
for (let i = 0; i < fileErrors.length; i++) {
|
|
1184
|
+
const error = fileErrors[i];
|
|
1185
|
+
await displayModernLinterError(error, filePath, i + 1, fileErrors.length);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
/**
|
|
1189
|
+
* Muestra un error individual con formato visual moderno tipo ESLint/Prettier
|
|
1190
|
+
*/
|
|
1191
|
+
async function displayModernLinterError(error, filePath, errorIndex, totalErrorsInFile) {
|
|
1192
|
+
const chalk = await loadChalk();
|
|
1193
|
+
const fs = await import('node:fs/promises');
|
|
1194
|
+
// Determinar tipo y color del error
|
|
1195
|
+
const isError = error.severity === 'error';
|
|
1196
|
+
const typeColor = isError ? chalk.red : chalk.yellow;
|
|
1197
|
+
const typeIcon = isError ? '✕' : '⚠';
|
|
1198
|
+
const line = error.line || 1;
|
|
1199
|
+
const column = error.column || 1;
|
|
1200
|
+
const ruleId = error.ruleId || error.from || 'unknown';
|
|
1201
|
+
// Línea principal del error con formato moderno
|
|
1202
|
+
const errorHeader = ` ${typeColor(typeIcon)} ${chalk.bold(error.message)}`;
|
|
1203
|
+
const ruleInfo = `${chalk.gray(ruleId)}`;
|
|
1204
|
+
const locationInfo = `${chalk.blue(`${line}:${column}`)}`;
|
|
1205
|
+
logger.info(errorHeader);
|
|
1206
|
+
logger.info(` ${chalk.gray('at')} ${locationInfo} ${chalk.gray('·')} ${ruleInfo}`);
|
|
1207
|
+
// Mostrar código con contexto
|
|
1208
|
+
try {
|
|
1209
|
+
const absolutePath = path.resolve(filePath);
|
|
1210
|
+
const fileContent = await fs.readFile(absolutePath, 'utf-8');
|
|
1211
|
+
const lines = fileContent.split('\n');
|
|
1212
|
+
const lineNum = parseInt(line.toString()) - 1;
|
|
1213
|
+
if (lineNum >= 0 && lineNum < lines.length) {
|
|
1214
|
+
logger.info('');
|
|
1215
|
+
// Mostrar líneas de contexto con numeración elegante
|
|
1216
|
+
const startLine = Math.max(0, lineNum - 1);
|
|
1217
|
+
const endLine = Math.min(lines.length - 1, lineNum + 1);
|
|
1218
|
+
const maxLineNumWidth = (endLine + 1).toString().length;
|
|
1219
|
+
for (let i = startLine; i <= endLine; i++) {
|
|
1220
|
+
const currentLineNum = i + 1;
|
|
1221
|
+
const currentLine = lines[i] || '';
|
|
1222
|
+
const lineNumStr = currentLineNum
|
|
1223
|
+
.toString()
|
|
1224
|
+
.padStart(maxLineNumWidth, ' ');
|
|
1225
|
+
const isErrorLine = i === lineNum;
|
|
1226
|
+
if (isErrorLine) {
|
|
1227
|
+
// Línea con el error - destacada
|
|
1228
|
+
logger.info(` ${chalk.red('>')} ${chalk.gray(lineNumStr)} ${chalk.gray('│')} ${currentLine}`);
|
|
1229
|
+
// Indicador de posición del error
|
|
1230
|
+
const pointer = ' '.repeat(Math.max(0, column - 1)) + typeColor('^');
|
|
1231
|
+
logger.info(` ${chalk.gray(' ')} ${chalk.gray(' '.repeat(maxLineNumWidth))} ${chalk.gray('│')} ${pointer}`);
|
|
1232
|
+
}
|
|
1233
|
+
else {
|
|
1234
|
+
// Líneas de contexto
|
|
1235
|
+
logger.info(` ${chalk.gray(' ')} ${chalk.gray(lineNumStr)} ${chalk.gray('│')} ${chalk.gray(currentLine)}`);
|
|
1236
|
+
}
|
|
1063
1237
|
}
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
catch {
|
|
1241
|
+
// Si no se puede leer el archivo, mostrar formato simplificado
|
|
1242
|
+
logger.info(` ${chalk.gray('│')} ${chalk.gray('(Unable to read file content)')}`);
|
|
1243
|
+
}
|
|
1244
|
+
// Mostrar ayuda si está disponible
|
|
1245
|
+
if (error.help) {
|
|
1246
|
+
logger.info('');
|
|
1247
|
+
const helpText = error.help.replace(/^Regla \w+: /, '').trim();
|
|
1248
|
+
logger.info(` ${chalk.blue('💡')} ${chalk.blue('Help:')} ${chalk.gray(helpText)}`);
|
|
1249
|
+
}
|
|
1250
|
+
// Separador entre errores (solo si no es el último)
|
|
1251
|
+
if (errorIndex < totalErrorsInFile) {
|
|
1252
|
+
logger.info('');
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Muestra un solo error del linter con formato visual mejorado
|
|
1257
|
+
* @deprecated Use displayModernLinterError instead
|
|
1258
|
+
*/
|
|
1259
|
+
async function _displaySingleLinterError(error, filePath) {
|
|
1260
|
+
const chalk = await loadChalk();
|
|
1261
|
+
const fs = await import('node:fs/promises');
|
|
1262
|
+
const icon = error.severity === 'error' ? '×' : '⚠';
|
|
1263
|
+
const ruleInfo = error.help || '';
|
|
1264
|
+
const line = error.line || 'N/A';
|
|
1265
|
+
const column = error.column || 10; // Columna por defecto si no está disponible
|
|
1266
|
+
// Línea principal del error
|
|
1267
|
+
const mainErrorLine = `${chalk.red(icon)} ${chalk.cyan(`${error.from}(${ruleInfo.replace(/^Regla \w+: /, '')})`)}: ${error.message}`;
|
|
1268
|
+
logger.info(mainErrorLine);
|
|
1269
|
+
// Intentar leer el contenido del archivo para mostrar contexto
|
|
1270
|
+
try {
|
|
1271
|
+
const absolutePath = path.resolve(filePath);
|
|
1272
|
+
const fileContent = await fs.readFile(absolutePath, 'utf-8');
|
|
1273
|
+
const lines = fileContent.split('\n');
|
|
1274
|
+
const lineNum = parseInt(line.toString()) - 1; // Convertir a índice 0-based
|
|
1275
|
+
if (lineNum >= 0 && lineNum < lines.length) {
|
|
1276
|
+
// Mostrar ubicación
|
|
1277
|
+
logger.info(chalk.blue(` ╭─[${filePath}:${line}:${column}]`));
|
|
1278
|
+
// Mostrar líneas de contexto
|
|
1279
|
+
const startLine = Math.max(0, lineNum - 1);
|
|
1280
|
+
const endLine = Math.min(lines.length - 1, lineNum + 1);
|
|
1281
|
+
for (let i = startLine; i <= endLine; i++) {
|
|
1282
|
+
const currentLineNum = i + 1;
|
|
1283
|
+
const currentLine = lines[i] || '';
|
|
1284
|
+
const prefix = currentLineNum.toString().padStart(2, ' ');
|
|
1285
|
+
if (i === lineNum) {
|
|
1286
|
+
// Línea con el error
|
|
1287
|
+
logger.info(chalk.blue(` ${prefix} │ `) + currentLine);
|
|
1288
|
+
// Mostrar el indicador de error
|
|
1289
|
+
const indent = ' '.repeat(prefix.length + 3); // Espacios para alinear
|
|
1290
|
+
const pointer = ' '.repeat(Math.max(0, (column || 1) - 1)) +
|
|
1291
|
+
chalk.red('───────┬──────');
|
|
1292
|
+
logger.info(chalk.blue(indent + '·') + pointer);
|
|
1293
|
+
// Mensaje de ubicación específica
|
|
1294
|
+
const messageIndent = ' '.repeat(Math.max(0, (column || 1) + 6));
|
|
1295
|
+
logger.info(chalk.blue(indent + '·') +
|
|
1296
|
+
messageIndent +
|
|
1297
|
+
chalk.red('╰── ') +
|
|
1298
|
+
chalk.gray(getErrorLocationMessage(error)));
|
|
1299
|
+
}
|
|
1300
|
+
else {
|
|
1301
|
+
// Líneas de contexto
|
|
1302
|
+
logger.info(chalk.blue(` ${prefix} │ `) + chalk.gray(currentLine));
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
logger.info(chalk.blue(' ╰────'));
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
catch {
|
|
1309
|
+
// Si no se puede leer el archivo, mostrar formato simplificado
|
|
1310
|
+
logger.info(chalk.blue(` ╭─[${filePath}:${line}:${column}]`));
|
|
1311
|
+
logger.info(chalk.blue(' │ ') +
|
|
1312
|
+
chalk.gray('(No se pudo leer el contenido del archivo)'));
|
|
1313
|
+
logger.info(chalk.blue(' ╰────'));
|
|
1314
|
+
}
|
|
1315
|
+
// Mostrar ayuda si está disponible
|
|
1316
|
+
if (error.help) {
|
|
1317
|
+
const helpMessage = error.help.replace(/^Regla \w+: /, '');
|
|
1318
|
+
logger.info(chalk.blue(' help: ') + chalk.yellow(helpMessage));
|
|
1319
|
+
}
|
|
1320
|
+
logger.info(''); // Espacio entre errores
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
* Genera un mensaje descriptivo para la ubicación específica del error
|
|
1324
|
+
*/
|
|
1325
|
+
function getErrorLocationMessage(error) {
|
|
1326
|
+
if (error.message.includes('declared but never used')) {
|
|
1327
|
+
const match = error.message.match(/'([^']+)'/);
|
|
1328
|
+
if (match) {
|
|
1329
|
+
return `'${match[1]}' is declared here`;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
if (error.message.includes('Unexpected var')) {
|
|
1333
|
+
return 'var declaration found here';
|
|
1334
|
+
}
|
|
1335
|
+
if (error.message.includes('never reassigned')) {
|
|
1336
|
+
const match = error.message.match(/'([^']+)'/);
|
|
1337
|
+
if (match) {
|
|
1338
|
+
return `'${match[1]}' is assigned here`;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
return 'error location';
|
|
1067
1342
|
}
|
|
1068
1343
|
/**
|
|
1069
1344
|
* Obtiene el color apropiado para cada etapa de compilación
|
|
@@ -1154,7 +1429,7 @@ class WatchModeOptimizer {
|
|
|
1154
1429
|
resolve({ success: true, cached: true });
|
|
1155
1430
|
return;
|
|
1156
1431
|
} // Configurar worker pool para modo watch
|
|
1157
|
-
const { TypeScriptWorkerPool } = await import('./typescript-worker-pool.js');
|
|
1432
|
+
const { TypeScriptWorkerPool } = (await import('./typescript-worker-pool.js'));
|
|
1158
1433
|
const workerPool = TypeScriptWorkerPool.getInstance();
|
|
1159
1434
|
workerPool.setMode('watch');
|
|
1160
1435
|
const result = await compileFn(filePath);
|
|
@@ -1185,11 +1460,12 @@ async function compileJS(inPath, outPath, mode = 'individual') {
|
|
|
1185
1460
|
const moduleManager = OptimizedModuleManager.getInstance();
|
|
1186
1461
|
// Timing de lectura
|
|
1187
1462
|
let start = Date.now();
|
|
1188
|
-
const extension = path.extname(inPath);
|
|
1189
|
-
// Asegurar que el parser esté cargado
|
|
1463
|
+
const extension = path.extname(inPath); // Asegurar que el parser esté cargado
|
|
1190
1464
|
await moduleManager.ensureModuleLoaded('parser');
|
|
1191
1465
|
const getCodeFile = await loadParser();
|
|
1192
|
-
|
|
1466
|
+
const result = await getCodeFile(inPath);
|
|
1467
|
+
let code = result.code;
|
|
1468
|
+
const error = result.error;
|
|
1193
1469
|
timings.fileRead = Date.now() - start;
|
|
1194
1470
|
if (error) {
|
|
1195
1471
|
await handleCompilationError(error instanceof Error ? error : new Error(String(error)), inPath, 'file-read', mode, env.VERBOSE === 'true');
|
|
@@ -1201,15 +1477,13 @@ async function compileJS(inPath, outPath, mode = 'individual') {
|
|
|
1201
1477
|
code === 'null') {
|
|
1202
1478
|
await handleCompilationError(new Error('El archivo está vacío o no se pudo leer.'), inPath, 'file-read', mode, env.VERBOSE === 'true');
|
|
1203
1479
|
throw new Error('El archivo está vacío o no se pudo leer.');
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
const shouldShowDetailedLogs = env.VERBOSE === 'true' && mode === 'all';
|
|
1207
|
-
// Compilación de Vue
|
|
1480
|
+
} // Logs detallados en modo verbose
|
|
1481
|
+
const shouldShowDetailedLogs = env.VERBOSE === 'true'; // Compilación de Vue
|
|
1208
1482
|
let vueResult;
|
|
1209
1483
|
if (extension === '.vue') {
|
|
1210
1484
|
start = Date.now();
|
|
1211
1485
|
if (shouldShowDetailedLogs) {
|
|
1212
|
-
logger.info(chalk.green(`💚 Precompilando VUE: ${inPath}`));
|
|
1486
|
+
logger.info(chalk.green(`💚 Precompilando VUE: ${path.basename(inPath)}`));
|
|
1213
1487
|
}
|
|
1214
1488
|
// Asegurar que el módulo Vue esté cargado
|
|
1215
1489
|
await moduleManager.ensureModuleLoaded('vue');
|
|
@@ -1242,7 +1516,7 @@ async function compileJS(inPath, outPath, mode = 'individual') {
|
|
|
1242
1516
|
if (extension === '.ts' || vueResult?.lang === 'ts') {
|
|
1243
1517
|
start = Date.now();
|
|
1244
1518
|
if (shouldShowDetailedLogs) {
|
|
1245
|
-
logger.info(chalk.blue(`🔄️ Precompilando TS: ${inPath}`));
|
|
1519
|
+
logger.info(chalk.blue(`🔄️ Precompilando TS: ${path.basename(inPath)}`));
|
|
1246
1520
|
}
|
|
1247
1521
|
// Asegurar que el módulo TypeScript esté cargado
|
|
1248
1522
|
await moduleManager.ensureModuleLoaded('typescript');
|
|
@@ -1277,10 +1551,9 @@ async function compileJS(inPath, outPath, mode = 'individual') {
|
|
|
1277
1551
|
if (!code || code.trim().length === 0) {
|
|
1278
1552
|
await handleCompilationError(new Error('El código TypeScript compilado está vacío.'), inPath, 'typescript', mode, env.VERBOSE === 'true');
|
|
1279
1553
|
throw new Error('El código TypeScript compilado está vacío.');
|
|
1280
|
-
}
|
|
1281
|
-
// Estandarización
|
|
1554
|
+
} // Estandarización
|
|
1282
1555
|
if (shouldShowDetailedLogs) {
|
|
1283
|
-
logger.info(chalk.yellow(`💛 Estandarizando: ${inPath}`));
|
|
1556
|
+
logger.info(chalk.yellow(`💛 Estandarizando: ${path.basename(inPath)}`));
|
|
1284
1557
|
}
|
|
1285
1558
|
start = Date.now();
|
|
1286
1559
|
// Asegurar que el módulo de transformaciones esté cargado
|
|
@@ -1305,7 +1578,7 @@ async function compileJS(inPath, outPath, mode = 'individual') {
|
|
|
1305
1578
|
if (env.isPROD === 'true') {
|
|
1306
1579
|
start = Date.now();
|
|
1307
1580
|
if (shouldShowDetailedLogs) {
|
|
1308
|
-
logger.info(chalk.red(`🤖 Minificando: ${inPath}`));
|
|
1581
|
+
logger.info(chalk.red(`🤖 Minificando: ${path.basename(inPath)}`));
|
|
1309
1582
|
}
|
|
1310
1583
|
// Asegurar que el módulo de minificación esté cargado
|
|
1311
1584
|
await moduleManager.ensureModuleLoaded('minify');
|
|
@@ -1325,11 +1598,26 @@ async function compileJS(inPath, outPath, mode = 'individual') {
|
|
|
1325
1598
|
}
|
|
1326
1599
|
registerCompilationSuccess(inPath, 'minification');
|
|
1327
1600
|
code = resultMinify.code;
|
|
1328
|
-
}
|
|
1329
|
-
// Escribir archivo final
|
|
1601
|
+
} // Escribir archivo final
|
|
1330
1602
|
const destinationDir = path.dirname(outPath);
|
|
1331
1603
|
await mkdir(destinationDir, { recursive: true });
|
|
1332
1604
|
await writeFile(outPath, code, 'utf-8');
|
|
1605
|
+
// Logs de timing detallados en modo verbose
|
|
1606
|
+
if (shouldShowDetailedLogs) {
|
|
1607
|
+
const totalTime = Object.values(timings).reduce((sum, time) => sum + time, 0);
|
|
1608
|
+
logger.info(chalk.cyan(`⏱️ Timing para ${path.basename(inPath)}:`));
|
|
1609
|
+
if (timings.fileRead)
|
|
1610
|
+
logger.info(chalk.cyan(` 📖 Lectura: ${timings.fileRead}ms`));
|
|
1611
|
+
if (timings.vueCompile)
|
|
1612
|
+
logger.info(chalk.cyan(` 💚 Vue: ${timings.vueCompile}ms`));
|
|
1613
|
+
if (timings.tsCompile)
|
|
1614
|
+
logger.info(chalk.cyan(` 🔄️ TypeScript: ${timings.tsCompile}ms`));
|
|
1615
|
+
if (timings.standardization)
|
|
1616
|
+
logger.info(chalk.cyan(` 💛 Estandarización: ${timings.standardization}ms`));
|
|
1617
|
+
if (timings.minification)
|
|
1618
|
+
logger.info(chalk.cyan(` 🤖 Minificación: ${timings.minification}ms`));
|
|
1619
|
+
logger.info(chalk.cyan(` 🏁 Total: ${totalTime}ms`));
|
|
1620
|
+
}
|
|
1333
1621
|
return {
|
|
1334
1622
|
error: null,
|
|
1335
1623
|
action: 'extension',
|
|
@@ -1362,6 +1650,20 @@ export async function initCompile(ruta, compileTailwind = true, mode = 'individu
|
|
|
1362
1650
|
const startTime = Date.now();
|
|
1363
1651
|
const file = normalizeRuta(ruta);
|
|
1364
1652
|
const outFile = getOutputPath(file);
|
|
1653
|
+
// 🚀 Verificar cache antes de compilar (especialmente importante en modo watch)
|
|
1654
|
+
if (mode === 'watch' || mode === 'individual') {
|
|
1655
|
+
if (await shouldSkipFile(file)) {
|
|
1656
|
+
if (env.VERBOSE === 'true') {
|
|
1657
|
+
logger.info(`⏭️ Archivo omitido (cache): ${path.basename(file)}`);
|
|
1658
|
+
}
|
|
1659
|
+
return {
|
|
1660
|
+
success: true,
|
|
1661
|
+
cached: true,
|
|
1662
|
+
output: smartCache.getOutputPath(file) || outFile,
|
|
1663
|
+
action: 'cached',
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1365
1667
|
if (mode === 'individual' && env.VERBOSE === 'true') {
|
|
1366
1668
|
logger.info(`🔜 Fuente: ${file}`);
|
|
1367
1669
|
}
|
|
@@ -1369,6 +1671,10 @@ export async function initCompile(ruta, compileTailwind = true, mode = 'individu
|
|
|
1369
1671
|
if (result.error) {
|
|
1370
1672
|
throw new Error(result.error);
|
|
1371
1673
|
}
|
|
1674
|
+
// 🚀 Actualizar cache después de compilación exitosa (especialmente en modo watch)
|
|
1675
|
+
if (mode === 'watch' || mode === 'individual') {
|
|
1676
|
+
await smartCache.set(file, outFile);
|
|
1677
|
+
}
|
|
1372
1678
|
const endTime = Date.now();
|
|
1373
1679
|
const elapsedTime = showTimingForHumans(endTime - startTime);
|
|
1374
1680
|
if (mode === 'individual') {
|
|
@@ -1399,6 +1705,183 @@ export async function initCompile(ruta, compileTailwind = true, mode = 'individu
|
|
|
1399
1705
|
}
|
|
1400
1706
|
// Variable para el último progreso mostrado (evitar spam)
|
|
1401
1707
|
let lastProgressUpdate = 0;
|
|
1708
|
+
// Sistema de gestión de progreso persistente (como Jest)
|
|
1709
|
+
class ProgressManager {
|
|
1710
|
+
static instance;
|
|
1711
|
+
progressActive = false;
|
|
1712
|
+
lastProgressLine = '';
|
|
1713
|
+
logBuffer = [];
|
|
1714
|
+
originalConsoleLog;
|
|
1715
|
+
originalConsoleError;
|
|
1716
|
+
originalConsoleWarn;
|
|
1717
|
+
hasProgressLine = false;
|
|
1718
|
+
constructor() {
|
|
1719
|
+
// Guardar referencias originales
|
|
1720
|
+
this.originalConsoleLog = console.log;
|
|
1721
|
+
this.originalConsoleError = console.error;
|
|
1722
|
+
this.originalConsoleWarn = console.warn;
|
|
1723
|
+
}
|
|
1724
|
+
static getInstance() {
|
|
1725
|
+
if (!ProgressManager.instance) {
|
|
1726
|
+
ProgressManager.instance = new ProgressManager();
|
|
1727
|
+
}
|
|
1728
|
+
return ProgressManager.instance;
|
|
1729
|
+
}
|
|
1730
|
+
interceptConsole() {
|
|
1731
|
+
// Interceptar console.log y similares
|
|
1732
|
+
console.log = (...args) => {
|
|
1733
|
+
this.addLog(args.map(arg => String(arg)).join(' '));
|
|
1734
|
+
};
|
|
1735
|
+
console.error = (...args) => {
|
|
1736
|
+
this.addLog(args.map(arg => String(arg)).join(' '));
|
|
1737
|
+
};
|
|
1738
|
+
console.warn = (...args) => {
|
|
1739
|
+
this.addLog(args.map(arg => String(arg)).join(' '));
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
restoreConsole() {
|
|
1743
|
+
console.log = this.originalConsoleLog;
|
|
1744
|
+
console.error = this.originalConsoleError;
|
|
1745
|
+
console.warn = this.originalConsoleWarn;
|
|
1746
|
+
}
|
|
1747
|
+
startProgress() {
|
|
1748
|
+
this.progressActive = true;
|
|
1749
|
+
this.logBuffer = [];
|
|
1750
|
+
this.hasProgressLine = false;
|
|
1751
|
+
this.interceptConsole();
|
|
1752
|
+
// 🎨 Header moderno de inicio de compilación
|
|
1753
|
+
const headerLine = '━'.repeat(48);
|
|
1754
|
+
process.stdout.write('\n\x1b[96m' + headerLine + '\x1b[0m\n');
|
|
1755
|
+
process.stdout.write('\x1b[96m│ \x1b[97m\x1b[1m🚀 Iniciando Compilación\x1b[0m\x1b[96m' +
|
|
1756
|
+
' '.repeat(22) +
|
|
1757
|
+
'│\x1b[0m\n');
|
|
1758
|
+
process.stdout.write('\x1b[96m' + headerLine + '\x1b[0m\n');
|
|
1759
|
+
}
|
|
1760
|
+
updateProgress(progressText) {
|
|
1761
|
+
if (!this.progressActive)
|
|
1762
|
+
return;
|
|
1763
|
+
// Si hay logs pendientes, mostrarlos primero
|
|
1764
|
+
if (this.logBuffer.length > 0) {
|
|
1765
|
+
// Si ya hay una línea de progreso, limpiarla primero
|
|
1766
|
+
if (this.hasProgressLine) {
|
|
1767
|
+
process.stdout.write('\r\x1b[K');
|
|
1768
|
+
}
|
|
1769
|
+
// Escribir todos los logs pendientes
|
|
1770
|
+
for (const log of this.logBuffer) {
|
|
1771
|
+
process.stdout.write((this.hasProgressLine ? '\n' : '') + log + '\n');
|
|
1772
|
+
this.hasProgressLine = false;
|
|
1773
|
+
}
|
|
1774
|
+
this.logBuffer = [];
|
|
1775
|
+
} // Escribir separador elegante antes del progreso
|
|
1776
|
+
if (this.hasProgressLine) {
|
|
1777
|
+
process.stdout.write('\r\x1b[K');
|
|
1778
|
+
}
|
|
1779
|
+
else {
|
|
1780
|
+
process.stdout.write('\n\x1b[96m' + '▔'.repeat(50) + '\x1b[0m\n');
|
|
1781
|
+
}
|
|
1782
|
+
// 🎨 Barra de progreso con colores dinámicos
|
|
1783
|
+
const stage = this.getStageFromText(progressText);
|
|
1784
|
+
const { bgColor, textColor, icon } = this.getProgressColors(stage);
|
|
1785
|
+
const progressBar = '█'.repeat(3);
|
|
1786
|
+
const enhancedProgress = `\x1b[${bgColor}m\x1b[${textColor}m ${progressBar} ${icon} ${progressText} ${progressBar} \x1b[0m`;
|
|
1787
|
+
process.stdout.write(enhancedProgress);
|
|
1788
|
+
this.hasProgressLine = true;
|
|
1789
|
+
this.lastProgressLine = progressText;
|
|
1790
|
+
}
|
|
1791
|
+
addLog(message) {
|
|
1792
|
+
if (this.progressActive) {
|
|
1793
|
+
this.logBuffer.push(message);
|
|
1794
|
+
}
|
|
1795
|
+
else {
|
|
1796
|
+
this.originalConsoleLog(message);
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
addImmediateLog(message) {
|
|
1800
|
+
if (this.progressActive) {
|
|
1801
|
+
if (this.hasProgressLine) {
|
|
1802
|
+
process.stdout.write('\r\x1b[K');
|
|
1803
|
+
}
|
|
1804
|
+
// Añadir un punto de separación visual para logs inmediatos
|
|
1805
|
+
process.stdout.write('\x1b[90m│\x1b[0m ' + message + '\n');
|
|
1806
|
+
this.hasProgressLine = false;
|
|
1807
|
+
}
|
|
1808
|
+
else {
|
|
1809
|
+
this.originalConsoleLog(message);
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
endProgress() {
|
|
1813
|
+
if (this.progressActive) {
|
|
1814
|
+
if (this.hasProgressLine) {
|
|
1815
|
+
process.stdout.write('\n');
|
|
1816
|
+
}
|
|
1817
|
+
// Mostrar barra de progreso final completa antes del separador
|
|
1818
|
+
process.stdout.write('\n\x1b[33m' + '-'.repeat(50) + '\x1b[0m\n');
|
|
1819
|
+
const finalProgressBar = '█'.repeat(3);
|
|
1820
|
+
const finalProgress = `\x1b[42m\x1b[30m ${finalProgressBar} ✅ PROCESO COMPLETADO 100% ${finalProgressBar} \x1b[0m`;
|
|
1821
|
+
process.stdout.write(finalProgress + '\n');
|
|
1822
|
+
// 🎨 Footer moderno de finalización
|
|
1823
|
+
const footerLine = '━'.repeat(48);
|
|
1824
|
+
process.stdout.write('\x1b[92m' + footerLine + '\x1b[0m\n');
|
|
1825
|
+
process.stdout.write('\x1b[92m│ \x1b[97m\x1b[1m✅ ¡Compilación Completada!\x1b[0m\x1b[92m' +
|
|
1826
|
+
' '.repeat(23) +
|
|
1827
|
+
'│\x1b[0m\n');
|
|
1828
|
+
process.stdout.write('\x1b[92m' + footerLine + '\x1b[0m\n\n');
|
|
1829
|
+
// Escribir logs finales pendientes
|
|
1830
|
+
if (this.logBuffer.length > 0) {
|
|
1831
|
+
for (const log of this.logBuffer) {
|
|
1832
|
+
process.stdout.write(log + '\n');
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
this.restoreConsole();
|
|
1837
|
+
this.progressActive = false;
|
|
1838
|
+
this.lastProgressLine = '';
|
|
1839
|
+
this.logBuffer = [];
|
|
1840
|
+
this.hasProgressLine = false;
|
|
1841
|
+
}
|
|
1842
|
+
isActive() {
|
|
1843
|
+
return this.progressActive;
|
|
1844
|
+
}
|
|
1845
|
+
/**
|
|
1846
|
+
* 🎨 Determina la etapa del progreso basándose en el texto
|
|
1847
|
+
*/
|
|
1848
|
+
getStageFromText(text) {
|
|
1849
|
+
if (text.includes('Iniciando') || text.includes('Starting'))
|
|
1850
|
+
return 'start';
|
|
1851
|
+
if (text.includes('Tailwind') || text.includes('CSS'))
|
|
1852
|
+
return 'tailwind';
|
|
1853
|
+
if (text.includes('Recopilando') ||
|
|
1854
|
+
text.includes('archivos') ||
|
|
1855
|
+
text.includes('files'))
|
|
1856
|
+
return 'files';
|
|
1857
|
+
if (text.includes('Compilando') || text.includes('workers'))
|
|
1858
|
+
return 'compile';
|
|
1859
|
+
if (text.includes('cache') || text.includes('Guardando'))
|
|
1860
|
+
return 'cache';
|
|
1861
|
+
if (text.includes('linter') || text.includes('Linter'))
|
|
1862
|
+
return 'linter';
|
|
1863
|
+
if (text.includes('completado') || text.includes('Complete'))
|
|
1864
|
+
return 'complete';
|
|
1865
|
+
return 'default';
|
|
1866
|
+
}
|
|
1867
|
+
/**
|
|
1868
|
+
* 🌈 Obtiene colores dinámicos para cada etapa
|
|
1869
|
+
*/
|
|
1870
|
+
getProgressColors(stage) {
|
|
1871
|
+
const colorSchemes = {
|
|
1872
|
+
start: { bgColor: '45', textColor: '97', icon: '🚀' }, // Cyan brillante
|
|
1873
|
+
tailwind: { bgColor: '105', textColor: '97', icon: '🎨' }, // Magenta
|
|
1874
|
+
files: { bgColor: '43', textColor: '30', icon: '📁' }, // Amarillo
|
|
1875
|
+
compile: { bgColor: '42', textColor: '30', icon: '⚙️' }, // Verde
|
|
1876
|
+
cache: { bgColor: '44', textColor: '97', icon: '💾' }, // Azul
|
|
1877
|
+
linter: { bgColor: '101', textColor: '97', icon: '🔍' }, // Rojo claro
|
|
1878
|
+
complete: { bgColor: '102', textColor: '30', icon: '✅' }, // Verde claro
|
|
1879
|
+
default: { bgColor: '100', textColor: '30', icon: '⏳' }, // Gris claro
|
|
1880
|
+
};
|
|
1881
|
+
const defaultColors = { bgColor: '100', textColor: '30', icon: '⏳' };
|
|
1882
|
+
return colorSchemes[stage] || defaultColors;
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1402
1885
|
// Función para ejecutar el linter antes de la compilación
|
|
1403
1886
|
export async function runLinter(showResult = false) {
|
|
1404
1887
|
const linterENV = env.linter;
|
|
@@ -1424,9 +1907,14 @@ export async function runLinter(showResult = false) {
|
|
|
1424
1907
|
// Procesar resultados de ESLint
|
|
1425
1908
|
if (Array.isArray(eslintResult.json)) {
|
|
1426
1909
|
eslintResult.json.forEach((result) => {
|
|
1910
|
+
const filePath = result.filePath ||
|
|
1911
|
+
result.file ||
|
|
1912
|
+
'archivo no especificado';
|
|
1427
1913
|
linterErrors.push({
|
|
1428
|
-
|
|
1429
|
-
|
|
1914
|
+
from: 'eslint',
|
|
1915
|
+
line: result.line || 'N/A',
|
|
1916
|
+
column: result.column || 1,
|
|
1917
|
+
file: filePath,
|
|
1430
1918
|
message: result.message,
|
|
1431
1919
|
severity: result.severity === 2
|
|
1432
1920
|
? 'error'
|
|
@@ -1443,9 +1931,16 @@ export async function runLinter(showResult = false) {
|
|
|
1443
1931
|
if (fileResult.messages &&
|
|
1444
1932
|
Array.isArray(fileResult.messages)) {
|
|
1445
1933
|
fileResult.messages.forEach((msg) => {
|
|
1934
|
+
const filePath = fileResult.filePath ||
|
|
1935
|
+
fileResult.file ||
|
|
1936
|
+
'archivo no especificado';
|
|
1446
1937
|
linterErrors.push({
|
|
1447
|
-
|
|
1448
|
-
|
|
1938
|
+
from: 'eslint',
|
|
1939
|
+
line: msg.line ||
|
|
1940
|
+
'N/A',
|
|
1941
|
+
column: msg.column ||
|
|
1942
|
+
1,
|
|
1943
|
+
file: filePath,
|
|
1449
1944
|
message: msg.message,
|
|
1450
1945
|
severity: msg.severity ===
|
|
1451
1946
|
2
|
|
@@ -1477,20 +1972,40 @@ export async function runLinter(showResult = false) {
|
|
|
1477
1972
|
.then((oxlintResult) => {
|
|
1478
1973
|
if (oxlintResult &&
|
|
1479
1974
|
oxlintResult['json'] &&
|
|
1480
|
-
Array.isArray(oxlintResult['json'])) {
|
|
1481
|
-
oxlintResult['json'].forEach((result) => {
|
|
1975
|
+
Array.isArray(oxlintResult['json']['diagnostics'])) {
|
|
1976
|
+
oxlintResult['json']['diagnostics'].forEach((result) => {
|
|
1977
|
+
const filePath = result.filename ||
|
|
1978
|
+
result.file ||
|
|
1979
|
+
'archivo no especificado';
|
|
1980
|
+
const lineNumber = result.labels &&
|
|
1981
|
+
result.labels[0] &&
|
|
1982
|
+
result.labels[0].span
|
|
1983
|
+
? result.labels[0].span
|
|
1984
|
+
.line ||
|
|
1985
|
+
result.labels[0].span
|
|
1986
|
+
.start?.line
|
|
1987
|
+
: 'N/A';
|
|
1988
|
+
const columnNumber = result.labels &&
|
|
1989
|
+
result.labels[0] &&
|
|
1990
|
+
result.labels[0].span
|
|
1991
|
+
? result.labels[0].span
|
|
1992
|
+
.column ||
|
|
1993
|
+
result.labels[0].span
|
|
1994
|
+
.start?.column
|
|
1995
|
+
: 1;
|
|
1482
1996
|
linterErrors.push({
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1997
|
+
from: 'oxlint',
|
|
1998
|
+
line: lineNumber,
|
|
1999
|
+
column: columnNumber,
|
|
2000
|
+
file: filePath,
|
|
1486
2001
|
message: result.message,
|
|
1487
2002
|
severity: typeof result.severity ===
|
|
1488
2003
|
'string'
|
|
1489
2004
|
? result.severity.toLowerCase()
|
|
1490
2005
|
: 'error',
|
|
1491
2006
|
help: result.help ||
|
|
1492
|
-
(result.
|
|
1493
|
-
? `Regla Oxlint: ${result.
|
|
2007
|
+
(result.code
|
|
2008
|
+
? `Regla Oxlint: ${result.code}`
|
|
1494
2009
|
: undefined),
|
|
1495
2010
|
});
|
|
1496
2011
|
});
|
|
@@ -1513,6 +2028,7 @@ export async function runLinter(showResult = false) {
|
|
|
1513
2028
|
}
|
|
1514
2029
|
await Promise.all(linterPromises);
|
|
1515
2030
|
if (showResult) {
|
|
2031
|
+
// Modo --linter: Solo mostrar resultados sin preguntar
|
|
1516
2032
|
if (linterErrors.length > 0) {
|
|
1517
2033
|
await displayLinterErrors(linterErrors);
|
|
1518
2034
|
}
|
|
@@ -1521,21 +2037,24 @@ export async function runLinter(showResult = false) {
|
|
|
1521
2037
|
logger.info(chalk.green('✅ No se encontraron errores ni advertencias de linting.'));
|
|
1522
2038
|
}
|
|
1523
2039
|
}
|
|
2040
|
+
else {
|
|
2041
|
+
// Modo compilación: Mostrar errores si los hay y preguntar al usuario
|
|
2042
|
+
if (linterErrors.length > 0) {
|
|
2043
|
+
await displayLinterErrors(linterErrors);
|
|
2044
|
+
logger.warn('🚨 Se encontraron errores o advertencias durante el linting.');
|
|
2045
|
+
if (env.yes === 'false') {
|
|
2046
|
+
const result = await promptUser('¿Deseas continuar con la compilación a pesar de los errores de linting? (s/N): ');
|
|
2047
|
+
if (result.toLowerCase() !== 's') {
|
|
2048
|
+
logger.info('🛑 Compilación cancelada por el usuario.');
|
|
2049
|
+
proceedWithCompilation = false;
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
1524
2054
|
}
|
|
1525
2055
|
catch (parseError) {
|
|
1526
2056
|
logger.warn(`Error parseando configuración de linter: ${parseError instanceof Error ? parseError.message : 'Error desconocido'}, omitiendo...`);
|
|
1527
2057
|
}
|
|
1528
|
-
if (!showResult && linterErrors.length > 0) {
|
|
1529
|
-
await displayLinterErrors(linterErrors);
|
|
1530
|
-
logger.warn('🚨 Se encontraron errores o advertencias durante el linting.');
|
|
1531
|
-
if (env.yes === 'false') {
|
|
1532
|
-
const result = await promptUser('¿Deseas continuar con la compilación a pesar de los errores de linting? (s/N): ');
|
|
1533
|
-
if (result.toLowerCase() !== 's') {
|
|
1534
|
-
logger.info('🛑 Compilación cancelada por el usuario.');
|
|
1535
|
-
proceedWithCompilation = false;
|
|
1536
|
-
}
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1539
2058
|
}
|
|
1540
2059
|
return proceedWithCompilation;
|
|
1541
2060
|
}
|
|
@@ -1557,23 +2076,47 @@ async function compileWithConcurrencyLimit(files, maxConcurrency = 8) {
|
|
|
1557
2076
|
const total = files.length;
|
|
1558
2077
|
let completed = 0;
|
|
1559
2078
|
let skipped = 0;
|
|
1560
|
-
let failed = 0;
|
|
2079
|
+
let failed = 0;
|
|
2080
|
+
// Usar el gestor de progreso existente (ya iniciado en initCompileAll)
|
|
2081
|
+
const progressManager = ProgressManager.getInstance();
|
|
2082
|
+
// Variable para controlar el progreso inicial
|
|
2083
|
+
let hasShownInitialProgress = false;
|
|
2084
|
+
// Contador para limpieza periódica de memoria
|
|
2085
|
+
let compilationCounter = 0;
|
|
2086
|
+
const CLEANUP_INTERVAL = 20; // Limpiar cada 20 compilaciones
|
|
2087
|
+
// Función para mostrar progreso
|
|
1561
2088
|
function showProgress() {
|
|
1562
2089
|
const currentTotal = completed + skipped + failed;
|
|
1563
2090
|
const progressBar = createProgressBar(currentTotal, total);
|
|
1564
2091
|
const progressPercent = Math.round((currentTotal / total) * 100);
|
|
1565
|
-
|
|
2092
|
+
// Mostrar progreso inicial cuando se inicie O cuando haya progreso real
|
|
2093
|
+
if ((currentTotal === 0 && !hasShownInitialProgress) ||
|
|
2094
|
+
(progressPercent > lastProgressUpdate + 1 && currentTotal > 0) ||
|
|
1566
2095
|
currentTotal === total) {
|
|
1567
|
-
|
|
2096
|
+
const progressText = `🚀 ${progressBar} [✅ ${completed} | ⏭️ ${skipped} | ❌ ${failed}]`;
|
|
2097
|
+
progressManager.updateProgress(progressText);
|
|
2098
|
+
if (currentTotal === 0) {
|
|
2099
|
+
hasShownInitialProgress = true;
|
|
2100
|
+
}
|
|
1568
2101
|
lastProgressUpdate = progressPercent;
|
|
2102
|
+
// NO terminar el progreso aquí - se termina en initCompileAll
|
|
1569
2103
|
}
|
|
1570
2104
|
}
|
|
2105
|
+
// Mostrar progreso inicial
|
|
2106
|
+
showProgress();
|
|
1571
2107
|
for (const file of files) {
|
|
1572
2108
|
const promise = (async () => {
|
|
1573
2109
|
try {
|
|
2110
|
+
// Log verbose: Iniciando compilación del archivo
|
|
2111
|
+
if (env.VERBOSE === 'true') {
|
|
2112
|
+
logger.info(`🔄 Compilando: ${path.basename(file)}`);
|
|
2113
|
+
}
|
|
1574
2114
|
// Verificar cache antes de compilar
|
|
1575
2115
|
if (await shouldSkipFile(file)) {
|
|
1576
2116
|
skipped++;
|
|
2117
|
+
if (env.VERBOSE === 'true') {
|
|
2118
|
+
logger.info(`⏭️ Archivo omitido (cache): ${path.basename(file)}`);
|
|
2119
|
+
}
|
|
1577
2120
|
showProgress();
|
|
1578
2121
|
return {
|
|
1579
2122
|
success: true,
|
|
@@ -1581,16 +2124,54 @@ async function compileWithConcurrencyLimit(files, maxConcurrency = 8) {
|
|
|
1581
2124
|
output: smartCache.getOutputPath(file),
|
|
1582
2125
|
};
|
|
1583
2126
|
}
|
|
1584
|
-
const result = await initCompile(file, false, 'batch');
|
|
2127
|
+
const result = await initCompile(file, false, 'batch');
|
|
2128
|
+
// Actualizar cache si la compilación fue exitosa
|
|
1585
2129
|
if (result.success && result.output) {
|
|
1586
2130
|
await smartCache.set(file, result.output);
|
|
2131
|
+
if (env.VERBOSE === 'true') {
|
|
2132
|
+
logger.info(`✅ Completado: ${path.basename(file)} → ${path.basename(result.output)}`);
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
else if (env.VERBOSE === 'true') {
|
|
2136
|
+
logger.info(`❌ Error en: ${path.basename(file)}`);
|
|
1587
2137
|
}
|
|
1588
2138
|
completed++;
|
|
2139
|
+
compilationCounter++; // Limpieza periódica de memoria
|
|
2140
|
+
if (compilationCounter % CLEANUP_INTERVAL === 0) {
|
|
2141
|
+
// Forzar garbage collection si está disponible
|
|
2142
|
+
try {
|
|
2143
|
+
if (typeof globalThis.gc === 'function') {
|
|
2144
|
+
globalThis.gc();
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
catch {
|
|
2148
|
+
// gc no disponible, continuar normalmente
|
|
2149
|
+
}
|
|
2150
|
+
// Limpiar cache si la memoria es alta
|
|
2151
|
+
const memUsage = process.memoryUsage();
|
|
2152
|
+
const heapUsedMB = memUsage.heapUsed / (1024 * 1024);
|
|
2153
|
+
if (heapUsedMB > 300) {
|
|
2154
|
+
// Si el heap supera 300MB
|
|
2155
|
+
const cacheEntries = smartCache.getStats().entries;
|
|
2156
|
+
if (cacheEntries > 50) {
|
|
2157
|
+
console.log(`[Memory] Heap alto (${heapUsedMB.toFixed(1)}MB), limpiando cache...`);
|
|
2158
|
+
// Limpiar entradas más antiguas del cache
|
|
2159
|
+
const removedEntries = smartCache.cleanOldEntries(20);
|
|
2160
|
+
if (removedEntries > 0) {
|
|
2161
|
+
console.log(`[Memory] Se removieron ${removedEntries} entradas del cache`);
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
1589
2166
|
showProgress();
|
|
1590
2167
|
return result;
|
|
1591
2168
|
}
|
|
1592
2169
|
catch (error) {
|
|
1593
2170
|
failed++;
|
|
2171
|
+
if (env.VERBOSE === 'true') {
|
|
2172
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2173
|
+
logger.error(`💥 Falló: ${path.basename(file)} - ${errorMsg}`);
|
|
2174
|
+
}
|
|
1594
2175
|
showProgress();
|
|
1595
2176
|
return {
|
|
1596
2177
|
success: false,
|
|
@@ -1606,18 +2187,26 @@ async function compileWithConcurrencyLimit(files, maxConcurrency = 8) {
|
|
|
1606
2187
|
}
|
|
1607
2188
|
}
|
|
1608
2189
|
await Promise.all(results);
|
|
1609
|
-
|
|
2190
|
+
// El progreso ya se termina automáticamente en showProgress() cuando se completa
|
|
1610
2191
|
}
|
|
1611
2192
|
export async function initCompileAll() {
|
|
1612
2193
|
try {
|
|
2194
|
+
// Inicializar el gestor de progreso desde el inicio
|
|
2195
|
+
const progressManager = ProgressManager.getInstance();
|
|
2196
|
+
progressManager.startProgress();
|
|
2197
|
+
// Fase 1: Preparación inicial
|
|
2198
|
+
progressManager.updateProgress('🚀 Iniciando compilación...');
|
|
1613
2199
|
// Limpiar estado de compilación anterior
|
|
1614
2200
|
clearCompilationState();
|
|
1615
2201
|
// Cargar cache al inicio
|
|
2202
|
+
progressManager.updateProgress('📦 Cargando cache...');
|
|
1616
2203
|
await loadCache();
|
|
1617
|
-
lastProgressUpdate = 0;
|
|
1618
|
-
|
|
2204
|
+
lastProgressUpdate = 0; // Fase 2: Linting
|
|
2205
|
+
progressManager.updateProgress('🔍 Ejecutando linter...');
|
|
2206
|
+
const shouldContinue = await runLinter(false); // false = mostrar errores y preguntar si hay errores
|
|
1619
2207
|
if (!shouldContinue) {
|
|
1620
2208
|
// await displayCompilationSummary(env.VERBOSE === 'true');
|
|
2209
|
+
progressManager.endProgress();
|
|
1621
2210
|
return;
|
|
1622
2211
|
}
|
|
1623
2212
|
const startTime = Date.now();
|
|
@@ -1633,7 +2222,9 @@ export async function initCompileAll() {
|
|
|
1633
2222
|
];
|
|
1634
2223
|
logger.info(`📝 Compilando todos los archivos...`);
|
|
1635
2224
|
logger.info(`🔜 Fuente: ${rawPathSource}`);
|
|
1636
|
-
logger.info(`🔚 Destino: ${pathDist}\n`);
|
|
2225
|
+
logger.info(`🔚 Destino: ${pathDist}\n`);
|
|
2226
|
+
// Fase 3: TailwindCSS
|
|
2227
|
+
progressManager.updateProgress('🎨 Generando TailwindCSS...');
|
|
1637
2228
|
const generateTailwindCSS = await loadTailwind();
|
|
1638
2229
|
const resultTW = await generateTailwindCSS();
|
|
1639
2230
|
if (typeof resultTW !== 'boolean') {
|
|
@@ -1643,7 +2234,9 @@ export async function initCompileAll() {
|
|
|
1643
2234
|
else {
|
|
1644
2235
|
await handleCompilationError(new Error(`${resultTW.message}${resultTW.details ? '\n' + resultTW.details : ''}`), 'tailwind.config.js', 'tailwind', 'all', env.VERBOSE === 'true');
|
|
1645
2236
|
}
|
|
1646
|
-
}
|
|
2237
|
+
}
|
|
2238
|
+
// Fase 4: Recopilando archivos
|
|
2239
|
+
progressManager.updateProgress('📁 Recopilando archivos...');
|
|
1647
2240
|
const filesToCompile = [];
|
|
1648
2241
|
for await (const file of glob(patterns)) {
|
|
1649
2242
|
if (file.endsWith('.d.ts')) {
|
|
@@ -1651,46 +2244,86 @@ export async function initCompileAll() {
|
|
|
1651
2244
|
}
|
|
1652
2245
|
// Usar la ruta tal como viene de glob, sin modificar
|
|
1653
2246
|
filesToCompile.push(file);
|
|
1654
|
-
}
|
|
1655
|
-
// Determinar concurrencia óptima
|
|
2247
|
+
} // Determinar concurrencia óptima considerando memoria disponible
|
|
1656
2248
|
const cpuCount = os.cpus().length;
|
|
1657
2249
|
const fileCount = filesToCompile.length;
|
|
2250
|
+
const memUsage = process.memoryUsage();
|
|
2251
|
+
const availableMemoryMB = (memUsage.heapTotal - memUsage.heapUsed) / (1024 * 1024);
|
|
1658
2252
|
let maxConcurrency;
|
|
1659
|
-
|
|
1660
|
-
|
|
2253
|
+
// Ajustar concurrencia basado en memoria disponible y archivos
|
|
2254
|
+
if (availableMemoryMB < 100) {
|
|
2255
|
+
// Poca memoria disponible
|
|
2256
|
+
maxConcurrency = Math.min(2, cpuCount);
|
|
2257
|
+
}
|
|
2258
|
+
else if (fileCount < 10) {
|
|
2259
|
+
maxConcurrency = Math.min(fileCount, Math.min(cpuCount, 4));
|
|
1661
2260
|
}
|
|
1662
2261
|
else if (fileCount < 50) {
|
|
1663
|
-
maxConcurrency = Math.min(cpuCount
|
|
2262
|
+
maxConcurrency = Math.min(cpuCount, 6); // Reducido
|
|
1664
2263
|
}
|
|
1665
2264
|
else {
|
|
1666
|
-
maxConcurrency = Math.min(cpuCount
|
|
2265
|
+
maxConcurrency = Math.min(cpuCount, 8); // Reducido
|
|
1667
2266
|
}
|
|
2267
|
+
// Fase 5: Configurando workers
|
|
2268
|
+
progressManager.updateProgress('⚙️ Configurando workers...');
|
|
1668
2269
|
logger.info(`🚀 Compilando ${fileCount} archivos con concurrencia optimizada (${maxConcurrency} hilos)...`); // Configurar worker pool para modo batch
|
|
1669
2270
|
try {
|
|
1670
|
-
const { TypeScriptWorkerPool } = await import('./typescript-worker-pool.js');
|
|
2271
|
+
const { TypeScriptWorkerPool } = (await import('./typescript-worker-pool.js'));
|
|
1671
2272
|
const workerPool = TypeScriptWorkerPool.getInstance();
|
|
1672
2273
|
workerPool.setMode('batch');
|
|
1673
2274
|
}
|
|
1674
2275
|
catch {
|
|
1675
2276
|
// Error silencioso en configuración del pool
|
|
1676
|
-
}
|
|
1677
|
-
|
|
1678
|
-
// Guardar cache al final
|
|
2277
|
+
} // Fase 6: Compilación (el progreso continúa en compileWithConcurrencyLimit)
|
|
2278
|
+
progressManager.updateProgress(`🚀 Iniciando compilación de ${fileCount} archivos...`);
|
|
2279
|
+
await compileWithConcurrencyLimit(filesToCompile, maxConcurrency); // Guardar cache al final
|
|
2280
|
+
progressManager.updateProgress('💾 Guardando cache...');
|
|
1679
2281
|
await saveCache();
|
|
1680
2282
|
const endTime = Date.now();
|
|
1681
|
-
const elapsedTime = showTimingForHumans(endTime - startTime);
|
|
1682
|
-
|
|
1683
|
-
|
|
2283
|
+
const elapsedTime = showTimingForHumans(endTime - startTime); // Finalizar progreso
|
|
2284
|
+
progressManager.endProgress();
|
|
2285
|
+
// Mostrar resumen de compilación con tiempo total
|
|
2286
|
+
await displayCompilationSummary(env.VERBOSE === 'true', elapsedTime);
|
|
1684
2287
|
}
|
|
1685
2288
|
catch (error) {
|
|
2289
|
+
// Asegurar que el progreso termine en caso de error
|
|
2290
|
+
const progressManager = ProgressManager.getInstance();
|
|
2291
|
+
if (progressManager.isActive()) {
|
|
2292
|
+
progressManager.endProgress();
|
|
2293
|
+
}
|
|
1686
2294
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1687
2295
|
logger.error(`🚩 Error al compilar todos los archivos: ${errorMessage}`);
|
|
1688
2296
|
// Registrar el error en el sistema unificado
|
|
1689
|
-
await handleCompilationError(error instanceof Error ? error : new Error(String(error)), 'compilación general', 'all', 'all', env.VERBOSE === 'true');
|
|
1690
|
-
// Mostrar resumen incluso si hay errores generales
|
|
2297
|
+
await handleCompilationError(error instanceof Error ? error : new Error(String(error)), 'compilación general', 'all', 'all', env.VERBOSE === 'true'); // Mostrar resumen incluso si hay errores generales
|
|
1691
2298
|
await displayCompilationSummary(env.VERBOSE === 'true');
|
|
1692
2299
|
}
|
|
1693
2300
|
}
|
|
2301
|
+
/**
|
|
2302
|
+
* 🎨 Obtiene icono apropiado para cada etapa
|
|
2303
|
+
*/
|
|
2304
|
+
function getStageIcon(stage) {
|
|
2305
|
+
const icons = {
|
|
2306
|
+
vue: '🎨',
|
|
2307
|
+
typescript: '📘',
|
|
2308
|
+
standardization: '💛',
|
|
2309
|
+
minification: '🗜️',
|
|
2310
|
+
tailwind: '🎨',
|
|
2311
|
+
'file-read': '📖',
|
|
2312
|
+
default: '⚙️',
|
|
2313
|
+
};
|
|
2314
|
+
return icons[stage] ?? '⚙️';
|
|
2315
|
+
}
|
|
2316
|
+
/**
|
|
2317
|
+
* Crea una barra de progreso visual con porcentaje
|
|
2318
|
+
*/
|
|
2319
|
+
function createProgressBarWithPercentage(percentage, width) {
|
|
2320
|
+
const filled = Math.round((percentage / 100) * width);
|
|
2321
|
+
const empty = width - filled;
|
|
2322
|
+
// Usar código directo para evitar problemas de importación
|
|
2323
|
+
const greenBar = '\x1b[32m' + '█'.repeat(filled) + '\x1b[0m';
|
|
2324
|
+
const grayBar = '\x1b[90m' + '░'.repeat(empty) + '\x1b[0m';
|
|
2325
|
+
return `${greenBar}${grayBar} ${percentage}%`;
|
|
2326
|
+
}
|
|
1694
2327
|
// Función wrapper para compatibilidad con tests
|
|
1695
2328
|
export async function compileFile(filePath) {
|
|
1696
2329
|
return await initCompile(filePath, true, 'individual');
|