versacompiler 1.0.4 → 2.0.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.
Files changed (41) hide show
  1. package/README.md +357 -145
  2. package/dist/compiler/compile.js +1120 -0
  3. package/dist/compiler/error-reporter.js +467 -0
  4. package/dist/compiler/linter.js +72 -0
  5. package/dist/{services → compiler}/minify.js +40 -31
  6. package/dist/compiler/parser.js +30 -0
  7. package/dist/compiler/tailwindcss.js +39 -0
  8. package/dist/compiler/transformTStoJS.js +16 -0
  9. package/dist/compiler/transforms.js +544 -0
  10. package/dist/compiler/typescript-error-parser.js +282 -0
  11. package/dist/compiler/typescript-sync-validator.js +230 -0
  12. package/dist/compiler/typescript-worker-thread.cjs +457 -0
  13. package/dist/compiler/typescript-worker.js +309 -0
  14. package/dist/compiler/typescript.js +382 -0
  15. package/dist/compiler/vuejs.js +296 -0
  16. package/dist/hrm/VueHRM.js +353 -0
  17. package/dist/hrm/errorScreen.js +23 -1
  18. package/dist/hrm/getInstanciaVue.js +313 -0
  19. package/dist/hrm/initHRM.js +140 -0
  20. package/dist/main.js +287 -0
  21. package/dist/servicios/browserSync.js +177 -0
  22. package/dist/servicios/chokidar.js +178 -0
  23. package/dist/servicios/logger.js +33 -0
  24. package/dist/servicios/readConfig.js +429 -0
  25. package/dist/utils/module-resolver.js +506 -0
  26. package/dist/utils/promptUser.js +48 -0
  27. package/dist/utils/resolve-bin.js +29 -0
  28. package/dist/utils/utils.js +21 -48
  29. package/dist/wrappers/eslint-node.js +145 -0
  30. package/dist/wrappers/oxlint-node.js +120 -0
  31. package/dist/wrappers/tailwind-node.js +92 -0
  32. package/package.json +62 -15
  33. package/dist/hrm/devMode.js +0 -249
  34. package/dist/hrm/instanciaVue.js +0 -35
  35. package/dist/hrm/setupHMR.js +0 -57
  36. package/dist/index.js +0 -873
  37. package/dist/services/acorn.js +0 -29
  38. package/dist/services/linter.js +0 -55
  39. package/dist/services/typescript.js +0 -89
  40. package/dist/services/vueLoader.js +0 -324
  41. package/dist/services/vuejs.js +0 -259
@@ -0,0 +1,1120 @@
1
+ import { glob, mkdir, readFile, stat, unlink, writeFile, } from 'node:fs/promises';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { env } from 'node:process';
5
+ // Lazy loading optimizations - Only import lightweight modules synchronously
6
+ import { logger } from '../servicios/logger.js';
7
+ import { promptUser } from '../utils/promptUser.js';
8
+ import { showTimingForHumans } from '../utils/utils.js';
9
+ // Heavy dependencies will be loaded dynamically when needed
10
+ let chalk;
11
+ let ESLint;
12
+ let OxLint;
13
+ let minifyJS;
14
+ let getCodeFile;
15
+ let generateTailwindCSS;
16
+ let estandarizaCode;
17
+ let preCompileTS;
18
+ let preCompileVue;
19
+ // 🚀 Sistema de Carga Inteligente de Módulos - VERSIÓN OPTIMIZADA
20
+ class ModuleManager {
21
+ static instance;
22
+ isInitialized = false;
23
+ initializationPromise = null;
24
+ loadedModules = new Set();
25
+ // NUEVOS: Gestión de modo y precarga
26
+ currentMode = null;
27
+ preloadPromises = new Map();
28
+ moduleCache = new Map();
29
+ constructor() { }
30
+ static getInstance() {
31
+ if (!ModuleManager.instance) {
32
+ ModuleManager.instance = new ModuleManager();
33
+ }
34
+ return ModuleManager.instance;
35
+ }
36
+ /**
37
+ * NUEVO: Precarga estratégica para modo watch
38
+ */
39
+ async preloadForWatchMode() {
40
+ const essentialModules = ['chalk', 'parser', 'transforms'];
41
+ const preloadPromises = essentialModules.map(async (moduleName) => {
42
+ if (!this.loadedModules.has(moduleName)) {
43
+ switch (moduleName) {
44
+ case 'chalk':
45
+ return this._loadModule('chalk', loadChalk);
46
+ case 'parser':
47
+ return this._loadModule('parser', loadParser);
48
+ case 'transforms':
49
+ return this._loadModule('transforms', loadTransforms);
50
+ }
51
+ }
52
+ });
53
+ await Promise.all(preloadPromises);
54
+ // console.log('[ModuleManager] Precarga completada para modo watch');
55
+ } /**
56
+ * MEJORADO: Inicializa los módulos necesarios según el contexto de compilación
57
+ * @param context Contexto de compilación: 'individual', 'batch', 'watch'
58
+ * @param fileExtensions Extensiones de archivos a compilar para optimizar la carga
59
+ */
60
+ async initializeModules(context = 'individual', fileExtensions = new Set()) {
61
+ // Si cambia el contexto, reinicializar
62
+ if (this.currentMode !== context) {
63
+ this.currentMode = context;
64
+ // En modo watch, precargar módulos esenciales
65
+ if (context === 'watch') {
66
+ await this.preloadForWatchMode();
67
+ }
68
+ }
69
+ if (this.initializationPromise) {
70
+ return this.initializationPromise;
71
+ }
72
+ if (this.isInitialized && context !== 'individual') {
73
+ return;
74
+ }
75
+ this.initializationPromise = this._performInitialization(context, fileExtensions);
76
+ await this.initializationPromise;
77
+ this.initializationPromise = null;
78
+ }
79
+ async _performInitialization(context, fileExtensions) {
80
+ const modulesToLoad = [];
81
+ // Módulos siempre necesarios
82
+ if (!this.loadedModules.has('chalk')) {
83
+ modulesToLoad.push(this._loadModule('chalk', loadChalk));
84
+ }
85
+ if (!this.loadedModules.has('parser')) {
86
+ modulesToLoad.push(this._loadModule('parser', loadParser));
87
+ }
88
+ if (!this.loadedModules.has('transforms')) {
89
+ modulesToLoad.push(this._loadModule('transforms', loadTransforms));
90
+ }
91
+ // Carga contextual según el tipo de compilación
92
+ if (context === 'batch' || context === 'watch') {
93
+ // En modo batch/watch, precargar todos los módulos necesarios
94
+ if (!this.loadedModules.has('vue')) {
95
+ modulesToLoad.push(this._loadModule('vue', loadVue));
96
+ }
97
+ if (!this.loadedModules.has('typescript')) {
98
+ modulesToLoad.push(this._loadModule('typescript', loadTypeScript));
99
+ }
100
+ if (!this.loadedModules.has('minify')) {
101
+ modulesToLoad.push(this._loadModule('minify', loadMinify));
102
+ }
103
+ }
104
+ else {
105
+ // En modo individual, cargar solo según las extensiones necesarias
106
+ if (fileExtensions.has('.vue') && !this.loadedModules.has('vue')) {
107
+ modulesToLoad.push(this._loadModule('vue', loadVue));
108
+ }
109
+ if ((fileExtensions.has('.ts') || fileExtensions.has('.vue')) &&
110
+ !this.loadedModules.has('typescript')) {
111
+ modulesToLoad.push(this._loadModule('typescript', loadTypeScript));
112
+ }
113
+ if (env.isPROD === 'true' && !this.loadedModules.has('minify')) {
114
+ modulesToLoad.push(this._loadModule('minify', loadMinify));
115
+ }
116
+ }
117
+ // Cargar módulos en paralelo
118
+ await Promise.all(modulesToLoad);
119
+ this.isInitialized = true;
120
+ }
121
+ async _loadModule(name, loadFunction) {
122
+ if (!this.loadedModules.has(name)) {
123
+ await loadFunction();
124
+ this.loadedModules.add(name);
125
+ }
126
+ }
127
+ /**
128
+ * Carga un módulo específico bajo demanda (lazy loading)
129
+ */
130
+ async ensureModuleLoaded(moduleName) {
131
+ if (this.loadedModules.has(moduleName)) {
132
+ return;
133
+ }
134
+ switch (moduleName) {
135
+ case 'vue':
136
+ await this._loadModule('vue', loadVue);
137
+ break;
138
+ case 'typescript':
139
+ await this._loadModule('typescript', loadTypeScript);
140
+ break;
141
+ case 'minify':
142
+ await this._loadModule('minify', loadMinify);
143
+ break;
144
+ case 'tailwind':
145
+ await this._loadModule('tailwind', loadTailwind);
146
+ break;
147
+ case 'linter':
148
+ await this._loadModule('linter', loadLinter);
149
+ break;
150
+ default:
151
+ throw new Error(`Módulo desconocido: ${moduleName}`);
152
+ }
153
+ }
154
+ /**
155
+ * Resetea el estado del manager (útil para tests)
156
+ */
157
+ reset() {
158
+ this.isInitialized = false;
159
+ this.initializationPromise = null;
160
+ this.loadedModules.clear();
161
+ }
162
+ /**
163
+ * Obtiene estadísticas de módulos cargados
164
+ */
165
+ getStats() {
166
+ return {
167
+ loaded: Array.from(this.loadedModules),
168
+ initialized: this.isInitialized,
169
+ };
170
+ }
171
+ }
172
+ // Lazy loading helper functions
173
+ async function loadChalk() {
174
+ if (!chalk) {
175
+ chalk = (await import('chalk')).default;
176
+ }
177
+ return chalk;
178
+ }
179
+ async function loadLinter() {
180
+ if (!ESLint || !OxLint) {
181
+ const linterModule = await import('./linter.js');
182
+ ESLint = linterModule.ESLint;
183
+ OxLint = linterModule.OxLint;
184
+ }
185
+ return { ESLint, OxLint };
186
+ }
187
+ async function loadMinify() {
188
+ if (!minifyJS) {
189
+ const minifyModule = await import('./minify.js');
190
+ minifyJS = minifyModule.minifyJS;
191
+ }
192
+ return minifyJS;
193
+ }
194
+ async function loadParser() {
195
+ if (!getCodeFile) {
196
+ const parserModule = await import('./parser.js');
197
+ getCodeFile = parserModule.getCodeFile;
198
+ }
199
+ return getCodeFile;
200
+ }
201
+ async function loadTailwind() {
202
+ if (!generateTailwindCSS) {
203
+ const tailwindModule = await import('./tailwindcss.js');
204
+ generateTailwindCSS = tailwindModule.generateTailwindCSS;
205
+ }
206
+ return generateTailwindCSS;
207
+ }
208
+ async function loadTransforms() {
209
+ if (!estandarizaCode) {
210
+ const transformsModule = await import('./transforms.js');
211
+ estandarizaCode = transformsModule.estandarizaCode;
212
+ }
213
+ return estandarizaCode;
214
+ }
215
+ async function loadTypeScript() {
216
+ if (!preCompileTS) {
217
+ const typescriptModule = await import('./typescript.js');
218
+ preCompileTS = typescriptModule.preCompileTS;
219
+ }
220
+ return preCompileTS;
221
+ }
222
+ async function loadVue() {
223
+ if (!preCompileVue) {
224
+ const vueModule = await import('./vuejs.js');
225
+ preCompileVue = vueModule.preCompileVue;
226
+ }
227
+ return preCompileVue;
228
+ }
229
+ // Almacenamiento global de errores y resultados
230
+ const compilationErrors = [];
231
+ const compilationResults = [];
232
+ const compilationCache = new Map();
233
+ const CACHE_DIR = path.join(path.resolve(env.PATH_PROY || process.cwd(), 'compiler'), '.cache');
234
+ const CACHE_FILE = path.join(CACHE_DIR, 'versacompile-cache.json');
235
+ async function loadCache() {
236
+ try {
237
+ if (env.cleanCache === 'true') {
238
+ compilationCache.clear();
239
+ try {
240
+ await unlink(CACHE_FILE);
241
+ }
242
+ catch {
243
+ // Ignorar errores al eliminar el archivo
244
+ }
245
+ }
246
+ const cacheData = await readFile(CACHE_FILE, 'utf-8');
247
+ const parsed = JSON.parse(cacheData);
248
+ for (const [key, value] of Object.entries(parsed)) {
249
+ compilationCache.set(key, value);
250
+ }
251
+ }
252
+ catch {
253
+ // Cache file doesn't exist or is invalid, start fresh
254
+ }
255
+ }
256
+ async function saveCache() {
257
+ try {
258
+ await mkdir(CACHE_DIR, { recursive: true });
259
+ const cacheData = Object.fromEntries(compilationCache);
260
+ await writeFile(CACHE_FILE, JSON.stringify(cacheData, null, 2));
261
+ }
262
+ catch {
263
+ // Ignore save errors
264
+ }
265
+ }
266
+ // 🎯 Funciones del Sistema Unificado de Manejo de Errores
267
+ /**
268
+ * Registra un error de compilación en el sistema unificado
269
+ */
270
+ function registerCompilationError(file, stage, message, severity = 'error', details, help) {
271
+ compilationErrors.push({
272
+ file,
273
+ stage,
274
+ message,
275
+ severity,
276
+ details,
277
+ help,
278
+ timestamp: Date.now(),
279
+ });
280
+ }
281
+ /**
282
+ * Registra un resultado de compilación (éxitos/errores por etapa)
283
+ */
284
+ function registerCompilationResult(stage, errors, success, files = []) {
285
+ const existingResult = compilationResults.find(r => r.stage === stage);
286
+ if (existingResult) {
287
+ existingResult.errors += errors;
288
+ existingResult.success += success;
289
+ existingResult.files.push(...files);
290
+ }
291
+ else {
292
+ compilationResults.push({
293
+ stage,
294
+ errors,
295
+ success,
296
+ files: [...files],
297
+ });
298
+ }
299
+ }
300
+ /**
301
+ * Maneja errores según el modo de compilación
302
+ */
303
+ async function handleCompilationError(error, fileName, stage, mode, isVerbose = false) {
304
+ const errorMessage = error instanceof Error ? error.message : error;
305
+ const errorDetails = error instanceof Error ? error.stack : undefined;
306
+ // Registrar el error en el sistema unificado
307
+ registerCompilationError(fileName, stage, errorMessage, 'error', errorDetails);
308
+ registerCompilationResult(stage, 1, 0, [fileName]); // Mostrar error inmediatamente solo en modo individual y watch
309
+ if (mode === 'individual' || mode === 'watch') {
310
+ const chalk = await loadChalk();
311
+ const baseName = path.basename(fileName);
312
+ const stageColor = await getStageColor(stage);
313
+ if (isVerbose) {
314
+ // Modo verbose: Mostrar error completo con contexto
315
+ logger.error(chalk.red(`❌ Error en etapa ${stageColor(stage)} - ${baseName}:`));
316
+ logger.error(chalk.red(errorMessage));
317
+ if (errorDetails && (stage === 'typescript' || stage === 'vue')) {
318
+ // Mostrar stack trace limitado para TypeScript y Vue
319
+ const stackLines = errorDetails.split('\n').slice(0, 5);
320
+ stackLines.forEach(line => {
321
+ if (line.trim()) {
322
+ logger.error(chalk.gray(` ${line.trim()}`));
323
+ }
324
+ });
325
+ }
326
+ }
327
+ else {
328
+ // Modo normal: Mostrar error simplificado
329
+ const firstLine = errorMessage.split('\n')[0];
330
+ logger.error(chalk.red(`❌ Error en ${stageColor(stage)}: ${baseName}`));
331
+ logger.error(chalk.red(` ${firstLine}`));
332
+ logger.info(chalk.yellow(`💡 Usa --verbose para ver detalles completos`));
333
+ }
334
+ }
335
+ // En modo 'all', los errores se acumulan silenciosamente para el resumen final
336
+ }
337
+ /**
338
+ * Registra un éxito de compilación
339
+ */
340
+ function registerCompilationSuccess(fileName, stage) {
341
+ registerCompilationResult(stage, 0, 1, [fileName]);
342
+ }
343
+ /**
344
+ * Limpia todos los errores y resultados acumulados
345
+ */
346
+ function clearCompilationState() {
347
+ compilationErrors.length = 0;
348
+ compilationResults.length = 0;
349
+ }
350
+ /**
351
+ * Muestra un resumen detallado de todos los errores de compilación
352
+ */
353
+ async function displayCompilationSummary(isVerbose = false) {
354
+ const chalk = await loadChalk();
355
+ if (compilationErrors.length === 0 && compilationResults.length === 0) {
356
+ logger.info(chalk.green('✅ No hay errores de compilación para mostrar.'));
357
+ return;
358
+ }
359
+ logger.info(chalk.bold('\n--- 📊 RESUMEN DE COMPILACIÓN ---'));
360
+ // Mostrar estadísticas por etapa
361
+ if (compilationResults.length > 0) {
362
+ logger.info(chalk.blue('\n🔍 Estadísticas por etapa:'));
363
+ for (const result of compilationResults) {
364
+ const totalFiles = result.success + result.errors;
365
+ const successRate = totalFiles > 0
366
+ ? Math.round((result.success / totalFiles) * 100)
367
+ : 0;
368
+ const statusIcon = result.errors === 0 ? '✅' : '❌';
369
+ const stageColor = await getStageColor(result.stage);
370
+ const statusText = `${result.success} éxitos, ${result.errors} errores`;
371
+ const coloredStatusText = result.errors === 0
372
+ ? chalk.green(statusText)
373
+ : chalk.red(statusText);
374
+ logger.info(`${statusIcon} ${stageColor(result.stage)}: ${coloredStatusText} (${successRate}% éxito)`);
375
+ }
376
+ }
377
+ // Mostrar errores detallados
378
+ if (compilationErrors.length > 0) {
379
+ logger.info(chalk.red(`\n❌ Se encontraron ${compilationErrors.length} errores:`));
380
+ // Agrupar errores por archivo para mejor organización
381
+ const errorsByFile = new Map();
382
+ compilationErrors.forEach(error => {
383
+ if (!errorsByFile.has(error.file)) {
384
+ errorsByFile.set(error.file, []);
385
+ }
386
+ errorsByFile.get(error.file).push(error);
387
+ });
388
+ // Mostrar errores por archivo
389
+ let fileIndex = 1;
390
+ for (const [filePath, fileErrors] of errorsByFile) {
391
+ const baseName = path.basename(filePath);
392
+ const errorCount = fileErrors.filter(e => e.severity === 'error').length;
393
+ const warningCount = fileErrors.filter(e => e.severity === 'warning').length;
394
+ logger.info(chalk.cyan(`\n📄 ${fileIndex}. ${baseName}`));
395
+ logger.info(chalk.gray(` Ruta: ${filePath}`));
396
+ logger.info(chalk.yellow(` ${errorCount} errores, ${warningCount} advertencias`));
397
+ for (const error of fileErrors) {
398
+ const icon = error.severity === 'error' ? '❌' : '⚠️';
399
+ const stageColor = await getStageColor(error.stage);
400
+ logger.info(` ${icon} [${stageColor(error.stage)}] ${error.message}`);
401
+ if (isVerbose && error.details) {
402
+ // En modo verbose, mostrar detalles adicionales
403
+ const detailLines = error.details.split('\n').slice(0, 5);
404
+ detailLines.forEach(line => {
405
+ if (line.trim()) {
406
+ logger.info(chalk.gray(` ${line.trim()}`));
407
+ }
408
+ });
409
+ }
410
+ if (error.help) {
411
+ logger.info(chalk.blue(` 💡 ${error.help}`));
412
+ }
413
+ }
414
+ fileIndex++;
415
+ }
416
+ // Mostrar totales finales
417
+ const totalErrors = compilationErrors.filter(e => e.severity === 'error').length;
418
+ const totalWarnings = compilationErrors.filter(e => e.severity === 'warning').length;
419
+ const totalFiles = errorsByFile.size;
420
+ logger.info(chalk.bold('\n--- 📈 ESTADÍSTICAS FINALES ---'));
421
+ logger.info(`📁 Archivos con errores: ${totalFiles}`);
422
+ logger.info(`❌ Total de errores: ${totalErrors}`);
423
+ logger.info(`⚠️ Total de advertencias: ${totalWarnings}`);
424
+ if (totalErrors > 0) {
425
+ logger.info(chalk.red('🚨 Compilación completada con errores que requieren atención.'));
426
+ }
427
+ else {
428
+ logger.info(chalk.yellow('✅ Compilación completada con solo advertencias.'));
429
+ }
430
+ }
431
+ else {
432
+ logger.info(chalk.green('✅ ¡Compilación exitosa sin errores!'));
433
+ }
434
+ logger.info(chalk.bold('--- FIN DEL RESUMEN ---\n'));
435
+ }
436
+ /**
437
+ * Muestra errores del linter de forma detallada
438
+ */
439
+ async function displayLinterErrors(errors) {
440
+ const chalk = await loadChalk();
441
+ logger.info(chalk.bold('--- Errores y Advertencias de Linting ---'));
442
+ const errorsByFile = new Map();
443
+ errors.forEach(error => {
444
+ if (!errorsByFile.has(error.file)) {
445
+ errorsByFile.set(error.file, []);
446
+ }
447
+ errorsByFile.get(error.file).push(error);
448
+ });
449
+ const totalErrors = errors.filter(e => e.severity === 'error').length;
450
+ const totalWarnings = errors.filter(e => e.severity === 'warning').length;
451
+ const totalFiles = errorsByFile.size;
452
+ logger.info(chalk.yellow(`📊 Resumen: ${totalErrors} errores, ${totalWarnings} advertencias en ${totalFiles} archivos\n`));
453
+ errorsByFile.forEach((fileErrors, filePath) => {
454
+ const baseName = path.basename(filePath);
455
+ logger.info(chalk.cyan(`\n📄 ${baseName}`));
456
+ fileErrors.forEach(error => {
457
+ const icon = error.severity === 'error' ? '❌' : '⚠️';
458
+ logger.info(`${icon} ${error.message}`);
459
+ if (error.help) {
460
+ logger.info(` └─ ${error.help}`);
461
+ }
462
+ });
463
+ });
464
+ logger.info(chalk.bold('--- Fin de Errores y Advertencias ---\n'));
465
+ }
466
+ /**
467
+ * Obtiene el color apropiado para cada etapa de compilación
468
+ */
469
+ async function getStageColor(stage) {
470
+ const chalk = await loadChalk();
471
+ switch (stage) {
472
+ case 'vue':
473
+ return chalk.green;
474
+ case 'typescript':
475
+ return chalk.blue;
476
+ case 'standardization':
477
+ return chalk.yellow;
478
+ case 'minification':
479
+ return chalk.red;
480
+ case 'tailwind':
481
+ return chalk.magenta;
482
+ case 'file-read':
483
+ return chalk.gray;
484
+ default:
485
+ return chalk.white;
486
+ }
487
+ }
488
+ export function normalizeRuta(ruta) {
489
+ if (path.isAbsolute(ruta)) {
490
+ return path.normalize(ruta).replace(/\\/g, '/');
491
+ }
492
+ const file = path
493
+ .normalize(!ruta.startsWith('.') ? './' + ruta : ruta)
494
+ .replace(/\\/g, '/');
495
+ const sourceForDist = file.startsWith('./') ? file : `./${file}`;
496
+ return sourceForDist;
497
+ }
498
+ export function getOutputPath(ruta) {
499
+ const pathSource = env.PATH_SOURCE ?? '';
500
+ const pathDist = env.PATH_DIST ?? '';
501
+ if (!pathSource || !pathDist) {
502
+ return ruta.replace(/\.(vue|ts)$/, '.js');
503
+ }
504
+ const normalizedRuta = path.normalize(ruta).replace(/\\/g, '/');
505
+ const normalizedSource = path.normalize(pathSource).replace(/\\/g, '/');
506
+ const normalizedDist = path.normalize(pathDist).replace(/\\/g, '/');
507
+ let outputPath;
508
+ if (normalizedRuta.includes(normalizedSource)) {
509
+ const relativePath = normalizedRuta
510
+ .substring(normalizedRuta.indexOf(normalizedSource) +
511
+ normalizedSource.length)
512
+ .replace(/^[/\\]/, '');
513
+ outputPath = path
514
+ .join(normalizedDist, relativePath)
515
+ .replace(/\\/g, '/');
516
+ }
517
+ else {
518
+ const fileName = path.basename(normalizedRuta);
519
+ outputPath = path.join(normalizedDist, fileName).replace(/\\/g, '/');
520
+ }
521
+ if (outputPath.includes('vue') || outputPath.includes('ts')) {
522
+ return outputPath.replace(/\.(vue|ts)$/, '.js');
523
+ }
524
+ else {
525
+ return outputPath;
526
+ }
527
+ }
528
+ // Optimización para modo watch: debouncing y cache de archivos
529
+ class WatchModeOptimizer {
530
+ static instance;
531
+ fileSystemCache = new Map();
532
+ debounceTimers = new Map();
533
+ DEBOUNCE_DELAY = 100; // 100ms debounce
534
+ static getInstance() {
535
+ if (!WatchModeOptimizer.instance) {
536
+ WatchModeOptimizer.instance = new WatchModeOptimizer();
537
+ }
538
+ return WatchModeOptimizer.instance;
539
+ }
540
+ async compileForWatch(filePath, compileFn) {
541
+ return new Promise(resolve => {
542
+ const existingTimer = this.debounceTimers.get(filePath);
543
+ if (existingTimer) {
544
+ clearTimeout(existingTimer);
545
+ }
546
+ const timer = setTimeout(async () => {
547
+ this.debounceTimers.delete(filePath);
548
+ try {
549
+ const stats = await stat(filePath);
550
+ const cached = this.fileSystemCache.get(filePath);
551
+ if (cached && cached.mtime >= stats.mtimeMs) {
552
+ resolve({ success: true, cached: true });
553
+ return;
554
+ } // Configurar worker para modo watch
555
+ const { TypeScriptWorkerManager } = await import('./typescript-worker.js');
556
+ const workerManager = TypeScriptWorkerManager.getInstance();
557
+ workerManager.setMode('watch');
558
+ const result = await compileFn(filePath);
559
+ this.fileSystemCache.set(filePath, {
560
+ mtime: stats.mtimeMs,
561
+ });
562
+ resolve(result);
563
+ }
564
+ catch (error) {
565
+ resolve({ success: false, error });
566
+ }
567
+ }, this.DEBOUNCE_DELAY);
568
+ this.debounceTimers.set(filePath, timer);
569
+ });
570
+ }
571
+ cleanup() {
572
+ this.debounceTimers.forEach(timer => clearTimeout(timer));
573
+ this.debounceTimers.clear();
574
+ this.fileSystemCache.clear();
575
+ }
576
+ }
577
+ async function compileJS(inPath, outPath, mode = 'individual') {
578
+ const timings = {};
579
+ // Si la ruta ya es absoluta, no la resolvamos de nuevo
580
+ inPath = path.isAbsolute(inPath)
581
+ ? normalizeRuta(inPath)
582
+ : normalizeRuta(path.resolve(inPath));
583
+ // 🚀 Usar ModuleManager para carga optimizada
584
+ const moduleManager = ModuleManager.getInstance();
585
+ // Timing de lectura
586
+ let start = Date.now();
587
+ const extension = path.extname(inPath);
588
+ // Asegurar que el parser esté cargado
589
+ await moduleManager.ensureModuleLoaded('parser');
590
+ const getCodeFile = await loadParser();
591
+ let { code, error } = await getCodeFile(inPath);
592
+ timings.fileRead = Date.now() - start;
593
+ if (error) {
594
+ await handleCompilationError(error instanceof Error ? error : new Error(String(error)), inPath, 'file-read', mode, env.VERBOSE === 'true');
595
+ throw new Error(error instanceof Error ? error.message : String(error));
596
+ }
597
+ if (!code ||
598
+ code.trim().length === 0 ||
599
+ code === 'undefined' ||
600
+ code === 'null') {
601
+ await handleCompilationError(new Error('El archivo está vacío o no se pudo leer.'), inPath, 'file-read', mode, env.VERBOSE === 'true');
602
+ throw new Error('El archivo está vacío o no se pudo leer.');
603
+ }
604
+ // Logs detallados solo en modo verbose + all
605
+ const shouldShowDetailedLogs = env.VERBOSE === 'true' && mode === 'all';
606
+ // Compilación de Vue
607
+ let vueResult;
608
+ if (extension === '.vue') {
609
+ start = Date.now();
610
+ if (shouldShowDetailedLogs) {
611
+ logger.info(chalk.green(`💚 Precompilando VUE: ${inPath}`));
612
+ }
613
+ // Asegurar que el módulo Vue esté cargado
614
+ await moduleManager.ensureModuleLoaded('vue');
615
+ const preCompileVue = await loadVue();
616
+ if (typeof preCompileVue !== 'function') {
617
+ throw new Error(`loadVue devolvió ${typeof preCompileVue} en lugar de una función para archivo: ${inPath}`);
618
+ }
619
+ vueResult = await preCompileVue(code, inPath, env.isPROD === 'true');
620
+ timings.vueCompile = Date.now() - start;
621
+ if (vueResult === undefined || vueResult === null) {
622
+ throw new Error(`preCompileVue devolvió ${vueResult} para archivo: ${inPath}`);
623
+ }
624
+ if (vueResult.error) {
625
+ await handleCompilationError(vueResult.error instanceof Error
626
+ ? vueResult.error
627
+ : new Error(String(vueResult.error)), inPath, 'vue', mode, env.VERBOSE === 'true');
628
+ throw new Error(vueResult.error instanceof Error
629
+ ? vueResult.error.message
630
+ : String(vueResult.error));
631
+ }
632
+ registerCompilationSuccess(inPath, 'vue');
633
+ code = vueResult.data;
634
+ }
635
+ if (!code || code.trim().length === 0) {
636
+ await handleCompilationError(new Error('El código Vue compilado está vacío.'), inPath, 'vue', mode, env.VERBOSE === 'true');
637
+ throw new Error('El código Vue compilado está vacío.');
638
+ }
639
+ // Compilación de TypeScript
640
+ let tsResult;
641
+ if (extension === '.ts' || vueResult?.lang === 'ts') {
642
+ start = Date.now();
643
+ if (shouldShowDetailedLogs) {
644
+ logger.info(chalk.blue(`🔄️ Precompilando TS: ${inPath}`));
645
+ }
646
+ // Asegurar que el módulo TypeScript esté cargado
647
+ await moduleManager.ensureModuleLoaded('typescript');
648
+ const preCompileTS = await loadTypeScript();
649
+ if (typeof preCompileTS !== 'function') {
650
+ throw new Error(`loadTypeScript devolvió ${typeof preCompileTS} en lugar de una función para archivo: ${inPath}`);
651
+ }
652
+ tsResult = await preCompileTS(code, inPath);
653
+ timings.tsCompile = Date.now() - start;
654
+ if (tsResult === undefined || tsResult === null) {
655
+ throw new Error(`preCompileTS devolvió ${tsResult} para archivo: ${inPath}`);
656
+ }
657
+ if (tsResult.error) {
658
+ if (mode === 'all') {
659
+ // En modo --all, registrar el error pero continuar la compilación
660
+ registerCompilationError(inPath, 'typescript', tsResult.error instanceof Error
661
+ ? tsResult.error.message
662
+ : String(tsResult.error), 'error');
663
+ }
664
+ else {
665
+ await handleCompilationError(tsResult.error, inPath, 'typescript', mode, env.VERBOSE === 'true');
666
+ throw new Error(tsResult.error instanceof Error
667
+ ? tsResult.error.message
668
+ : String(tsResult.error));
669
+ }
670
+ }
671
+ else {
672
+ registerCompilationSuccess(inPath, 'typescript');
673
+ code = tsResult.data;
674
+ }
675
+ }
676
+ if (!code || code.trim().length === 0) {
677
+ await handleCompilationError(new Error('El código TypeScript compilado está vacío.'), inPath, 'typescript', mode, env.VERBOSE === 'true');
678
+ throw new Error('El código TypeScript compilado está vacío.');
679
+ }
680
+ // Estandarización
681
+ if (shouldShowDetailedLogs) {
682
+ logger.info(chalk.yellow(`💛 Estandarizando: ${inPath}`));
683
+ }
684
+ start = Date.now();
685
+ // Asegurar que el módulo de transformaciones esté cargado
686
+ await moduleManager.ensureModuleLoaded('transforms');
687
+ const estandarizaCode = await loadTransforms();
688
+ const resultSTD = await estandarizaCode(code, inPath);
689
+ timings.standardization = Date.now() - start;
690
+ if (resultSTD === undefined || resultSTD === null) {
691
+ throw new Error(`estandarizaCode devolvió ${resultSTD} para archivo: ${inPath}`);
692
+ }
693
+ if (resultSTD.error) {
694
+ await handleCompilationError(new Error(resultSTD.error), inPath, 'standardization', mode, env.VERBOSE === 'true');
695
+ throw new Error(resultSTD.error);
696
+ }
697
+ registerCompilationSuccess(inPath, 'standardization');
698
+ code = resultSTD.code;
699
+ if (!code || code.trim().length === 0) {
700
+ await handleCompilationError(new Error('El código estandarizado está vacío.'), inPath, 'standardization', mode, env.VERBOSE === 'true');
701
+ throw new Error('El código estandarizado está vacío.');
702
+ }
703
+ // Minificación (solo en producción)
704
+ if (env.isPROD === 'true') {
705
+ start = Date.now();
706
+ if (shouldShowDetailedLogs) {
707
+ logger.info(chalk.red(`🤖 Minificando: ${inPath}`));
708
+ }
709
+ // Asegurar que el módulo de minificación esté cargado
710
+ await moduleManager.ensureModuleLoaded('minify');
711
+ const minifyJS = await loadMinify();
712
+ const resultMinify = await minifyJS(code, inPath, true);
713
+ timings.minification = Date.now() - start;
714
+ if (resultMinify === undefined || resultMinify === null) {
715
+ throw new Error(`minifyJS devolvió ${resultMinify} para archivo: ${inPath}`);
716
+ }
717
+ if (resultMinify.error) {
718
+ await handleCompilationError(resultMinify.error instanceof Error
719
+ ? resultMinify.error
720
+ : new Error(String(resultMinify.error)), inPath, 'minification', mode, env.VERBOSE === 'true');
721
+ throw new Error(resultMinify.error instanceof Error
722
+ ? resultMinify.error.message
723
+ : String(resultMinify.error));
724
+ }
725
+ registerCompilationSuccess(inPath, 'minification');
726
+ code = resultMinify.code;
727
+ }
728
+ // Escribir archivo final
729
+ const destinationDir = path.dirname(outPath);
730
+ await mkdir(destinationDir, { recursive: true });
731
+ await writeFile(outPath, code, 'utf-8');
732
+ if (env.VERBOSE === 'true') {
733
+ logger.info(`\n📊 Timings para ${path.basename(inPath)}:`, JSON.stringify(timings));
734
+ }
735
+ return {
736
+ error: null,
737
+ action: 'extension',
738
+ };
739
+ }
740
+ export async function initCompile(ruta, compileTailwind = true, mode = 'individual') {
741
+ try {
742
+ // 🚀 Sistema de Carga Inteligente de Módulos
743
+ const moduleManager = ModuleManager.getInstance();
744
+ const fileExtension = path.extname(ruta);
745
+ const fileExtensions = new Set([fileExtension]);
746
+ // Inicializar módulos según el contexto
747
+ await moduleManager.initializeModules(mode === 'all' ? 'batch' : mode, fileExtensions);
748
+ // Generar TailwindCSS si está habilitado
749
+ if (compileTailwind && Boolean(env.TAILWIND)) {
750
+ await moduleManager.ensureModuleLoaded('tailwind');
751
+ const generateTailwindCSS = await loadTailwind();
752
+ const resultTW = await generateTailwindCSS();
753
+ if (typeof resultTW !== 'boolean') {
754
+ if (resultTW?.success) {
755
+ logger.info(`🎨 ${resultTW.message}`);
756
+ }
757
+ else {
758
+ const errorMsg = `${resultTW.message}${resultTW.details ? '\n' + resultTW.details : ''}`;
759
+ await handleCompilationError(new Error(errorMsg), 'tailwind.config.js', 'tailwind', mode, env.VERBOSE === 'true');
760
+ // No hacer throw aquí, permitir que la compilación continúe
761
+ }
762
+ }
763
+ }
764
+ const startTime = Date.now();
765
+ const file = normalizeRuta(ruta);
766
+ const outFile = getOutputPath(file);
767
+ if (mode === 'individual' && env.VERBOSE === 'true') {
768
+ logger.info(`🔜 Fuente: ${file}`);
769
+ }
770
+ const result = await compileJS(file, outFile, mode);
771
+ if (result.error) {
772
+ throw new Error(result.error);
773
+ }
774
+ const endTime = Date.now();
775
+ const elapsedTime = showTimingForHumans(endTime - startTime);
776
+ if (mode === 'individual') {
777
+ if (env.VERBOSE === 'true') {
778
+ logger.info(`🔚 Destino: ${outFile}`);
779
+ logger.info(`⏱️ Tiempo: ${elapsedTime}`);
780
+ }
781
+ const chalk = await loadChalk();
782
+ logger.info(chalk.green(`✅ Compilación exitosa: ${path.basename(file)}`));
783
+ }
784
+ return {
785
+ success: true,
786
+ output: outFile,
787
+ action: result.action,
788
+ };
789
+ }
790
+ catch (error) {
791
+ const errorMessage = error instanceof Error ? error.message : String(error);
792
+ if (env.VERBOSE === 'true') {
793
+ logger.error(`❌ Error en compilación de ${path.basename(ruta)}: ${errorMessage}`);
794
+ }
795
+ return {
796
+ success: false,
797
+ output: '',
798
+ error: errorMessage,
799
+ };
800
+ }
801
+ }
802
+ // Variable para el último progreso mostrado (evitar spam)
803
+ let lastProgressUpdate = 0;
804
+ // Función para ejecutar el linter antes de la compilación
805
+ export async function runLinter(showResult = false) {
806
+ const linterENV = env.linter;
807
+ const linterPromises = [];
808
+ const linterErrors = [];
809
+ let proceedWithCompilation = true;
810
+ if (env.ENABLE_LINTER !== 'true') {
811
+ return true;
812
+ }
813
+ if (typeof linterENV === 'string' && linterENV.trim() !== '') {
814
+ logger.info('🔍 Ejecutando linting...');
815
+ try {
816
+ const parsedLinterEnv = JSON.parse(linterENV);
817
+ if (Array.isArray(parsedLinterEnv)) {
818
+ // Cargar dependencias de linting de forma lazy
819
+ const { ESLint, OxLint } = await loadLinter();
820
+ for (const item of parsedLinterEnv) {
821
+ if (item.name.toLowerCase() === 'eslint') {
822
+ logger.info(`🔧 Ejecutando ESLint con config: ${item.configFile || 'por defecto'}`);
823
+ const eslintPromise = ESLint(item)
824
+ .then((eslintResult) => {
825
+ if (eslintResult && eslintResult.json) {
826
+ // Procesar resultados de ESLint
827
+ if (Array.isArray(eslintResult.json)) {
828
+ eslintResult.json.forEach((result) => {
829
+ linterErrors.push({
830
+ file: result.filePath ||
831
+ 'archivo no especificado',
832
+ message: result.message,
833
+ severity: result.severity === 2
834
+ ? 'error'
835
+ : 'warning',
836
+ help: result.ruleId
837
+ ? `Regla ESLint: ${result.ruleId}`
838
+ : undefined,
839
+ });
840
+ });
841
+ }
842
+ else if (eslintResult.json.results &&
843
+ Array.isArray(eslintResult.json.results)) {
844
+ eslintResult.json.results.forEach((fileResult) => {
845
+ if (fileResult.messages &&
846
+ Array.isArray(fileResult.messages)) {
847
+ fileResult.messages.forEach((msg) => {
848
+ linterErrors.push({
849
+ file: fileResult.filePath ||
850
+ 'archivo no especificado',
851
+ message: msg.message,
852
+ severity: msg.severity ===
853
+ 2
854
+ ? 'error'
855
+ : 'warning',
856
+ help: msg.ruleId
857
+ ? `Regla ESLint: ${msg.ruleId}`
858
+ : undefined,
859
+ });
860
+ });
861
+ }
862
+ });
863
+ }
864
+ }
865
+ })
866
+ .catch((err) => {
867
+ logger.error(`❌ Error durante la ejecución de ESLint: ${err.message}`);
868
+ linterErrors.push({
869
+ file: item.configFile || 'ESLint Config',
870
+ message: `Fallo al ejecutar ESLint: ${err.message}`,
871
+ severity: 'error',
872
+ });
873
+ });
874
+ linterPromises.push(eslintPromise);
875
+ }
876
+ else if (item.name.toLowerCase() === 'oxlint') {
877
+ logger.info(`🔧 Ejecutando OxLint con config: ${item.configFile || 'por defecto'}`);
878
+ const oxlintPromise = OxLint(item)
879
+ .then((oxlintResult) => {
880
+ if (oxlintResult &&
881
+ oxlintResult['json'] &&
882
+ Array.isArray(oxlintResult['json'])) {
883
+ oxlintResult['json'].forEach((result) => {
884
+ linterErrors.push({
885
+ file: result.filename ||
886
+ result.file ||
887
+ 'archivo no especificado',
888
+ message: result.message,
889
+ severity: typeof result.severity ===
890
+ 'string'
891
+ ? result.severity.toLowerCase()
892
+ : 'error',
893
+ help: result.help ||
894
+ (result.rule_id
895
+ ? `Regla Oxlint: ${result.rule_id}`
896
+ : undefined),
897
+ });
898
+ });
899
+ }
900
+ })
901
+ .catch((err) => {
902
+ logger.error(`❌ Error durante la ejecución de OxLint: ${err.message}`);
903
+ linterErrors.push({
904
+ file: item.configFile || 'Oxlint Config',
905
+ message: `Fallo al ejecutar Oxlint: ${err.message}`,
906
+ severity: 'error',
907
+ });
908
+ });
909
+ linterPromises.push(oxlintPromise);
910
+ }
911
+ }
912
+ }
913
+ else {
914
+ logger.warn('⚠️ La configuración de linter no es un array válido.');
915
+ }
916
+ await Promise.all(linterPromises);
917
+ if (showResult) {
918
+ if (linterErrors.length > 0) {
919
+ await displayLinterErrors(linterErrors);
920
+ }
921
+ else {
922
+ const chalk = await loadChalk();
923
+ logger.info(chalk.green('✅ No se encontraron errores ni advertencias de linting.'));
924
+ }
925
+ }
926
+ }
927
+ catch (parseError) {
928
+ logger.warn(`Error parseando configuración de linter: ${parseError instanceof Error ? parseError.message : 'Error desconocido'}, omitiendo...`);
929
+ }
930
+ if (!showResult && linterErrors.length > 0) {
931
+ await displayLinterErrors(linterErrors);
932
+ logger.warn('🚨 Se encontraron errores o advertencias durante el linting.');
933
+ if (env.yes === 'false') {
934
+ const result = await promptUser('¿Deseas continuar con la compilación a pesar de los errores de linting? (s/N): ');
935
+ if (result.toLowerCase() !== 's') {
936
+ logger.info('🛑 Compilación cancelada por el usuario.');
937
+ proceedWithCompilation = false;
938
+ }
939
+ }
940
+ }
941
+ }
942
+ return proceedWithCompilation;
943
+ }
944
+ // Función para crear una barra de progreso visual
945
+ function createProgressBar(current, total, width = 30) {
946
+ const percentage = Math.round((current / total) * 100);
947
+ const filled = Math.round((percentage / 100) * width);
948
+ const empty = width - filled;
949
+ return `[${'█'.repeat(filled)}${' '.repeat(empty)}] ${percentage}% (${current}/${total})`;
950
+ }
951
+ // Función helper para verificar si un archivo debe ser omitido por cache
952
+ async function shouldSkipFile(filePath) {
953
+ try {
954
+ const stats = await stat(filePath);
955
+ const cacheEntry = compilationCache.get(filePath);
956
+ if (!cacheEntry) {
957
+ return false; // No hay entrada en cache, debe compilarse
958
+ }
959
+ // Verificar si el archivo no ha cambiado desde la última compilación
960
+ if (stats.mtimeMs <= cacheEntry.mtime) {
961
+ // Verificar si el archivo de salida existe
962
+ try {
963
+ await stat(cacheEntry.outputPath);
964
+ return true; // Archivo existe y no ha cambiado, se puede omitir
965
+ }
966
+ catch {
967
+ return false; // Archivo de salida no existe, debe recompilarse
968
+ }
969
+ }
970
+ return false; // Archivo ha cambiado, debe recompilarse
971
+ }
972
+ catch {
973
+ return false; // Error al verificar, compilar por seguridad
974
+ }
975
+ }
976
+ // Función para compilar archivos con límite de concurrencia
977
+ async function compileWithConcurrencyLimit(files, maxConcurrency = 8) {
978
+ const results = [];
979
+ const executing = [];
980
+ const total = files.length;
981
+ let completed = 0;
982
+ let skipped = 0;
983
+ let failed = 0; // Función para mostrar progreso
984
+ function showProgress() {
985
+ const currentTotal = completed + skipped + failed;
986
+ const progressBar = createProgressBar(currentTotal, total);
987
+ const progressPercent = Math.round((currentTotal / total) * 100);
988
+ if (progressPercent > lastProgressUpdate + 1 ||
989
+ currentTotal === total) {
990
+ process.stdout.write(`\r🚀 ${progressBar} [✅ ${completed} | ⏭️ ${skipped} | ❌ ${failed}]`);
991
+ lastProgressUpdate = progressPercent;
992
+ }
993
+ }
994
+ for (const file of files) {
995
+ const promise = (async () => {
996
+ try {
997
+ // Verificar cache antes de compilar
998
+ if (await shouldSkipFile(file)) {
999
+ skipped++;
1000
+ showProgress();
1001
+ return {
1002
+ success: true,
1003
+ cached: true,
1004
+ output: compilationCache.get(file)?.outputPath || '',
1005
+ };
1006
+ }
1007
+ const result = await initCompile(file, false, 'batch');
1008
+ // Actualizar cache si la compilación fue exitosa
1009
+ if (result.success && result.output) {
1010
+ const stats = await stat(file);
1011
+ compilationCache.set(file, {
1012
+ hash: '', // Se podría implementar hash del contenido si es necesario
1013
+ mtime: stats.mtimeMs,
1014
+ outputPath: result.output,
1015
+ });
1016
+ }
1017
+ completed++;
1018
+ showProgress();
1019
+ return result;
1020
+ }
1021
+ catch (error) {
1022
+ failed++;
1023
+ showProgress();
1024
+ return {
1025
+ success: false,
1026
+ error: error instanceof Error ? error.message : String(error),
1027
+ };
1028
+ }
1029
+ })();
1030
+ results.push(promise);
1031
+ executing.push(promise);
1032
+ if (executing.length >= maxConcurrency) {
1033
+ await Promise.race(executing);
1034
+ executing.splice(executing.findIndex(p => p === promise), 1);
1035
+ }
1036
+ }
1037
+ await Promise.all(results);
1038
+ console.log('\n'); // Nueva línea después de la barra de progreso
1039
+ }
1040
+ export async function initCompileAll() {
1041
+ try {
1042
+ // Limpiar estado de compilación anterior
1043
+ clearCompilationState();
1044
+ // Cargar cache al inicio
1045
+ await loadCache();
1046
+ lastProgressUpdate = 0;
1047
+ const shouldContinue = await runLinter();
1048
+ if (!shouldContinue) {
1049
+ // await displayCompilationSummary(env.VERBOSE === 'true');
1050
+ return;
1051
+ }
1052
+ const startTime = Date.now();
1053
+ const rawPathSource = env.PATH_SOURCE ?? '';
1054
+ const pathDist = env.PATH_DIST ?? '';
1055
+ const normalizedGlobPathSource = rawPathSource.replace(/\\/g, '/');
1056
+ const patterns = [
1057
+ `${normalizedGlobPathSource}/**/*.js`,
1058
+ `${normalizedGlobPathSource}/**/*.vue`,
1059
+ `${normalizedGlobPathSource}/**/*.ts`,
1060
+ `${normalizedGlobPathSource}/**/*.mjs`,
1061
+ `${normalizedGlobPathSource}/**/*.cjs`,
1062
+ ];
1063
+ logger.info(`📝 Compilando todos los archivos...`);
1064
+ logger.info(`🔜 Fuente: ${rawPathSource}`);
1065
+ logger.info(`🔚 Destino: ${pathDist}\n`); // Generar TailwindCSS
1066
+ const generateTailwindCSS = await loadTailwind();
1067
+ const resultTW = await generateTailwindCSS();
1068
+ if (typeof resultTW !== 'boolean') {
1069
+ if (resultTW?.success) {
1070
+ logger.info(`🎨 ${resultTW.message}\n`);
1071
+ }
1072
+ else {
1073
+ await handleCompilationError(new Error(`${resultTW.message}${resultTW.details ? '\n' + resultTW.details : ''}`), 'tailwind.config.js', 'tailwind', 'all', env.VERBOSE === 'true');
1074
+ }
1075
+ } // Recopilar todos los archivos
1076
+ const filesToCompile = [];
1077
+ for await (const file of glob(patterns)) {
1078
+ if (file.endsWith('.d.ts')) {
1079
+ continue;
1080
+ }
1081
+ // Usar la ruta tal como viene de glob, sin modificar
1082
+ filesToCompile.push(file);
1083
+ }
1084
+ // Determinar concurrencia óptima
1085
+ const cpuCount = os.cpus().length;
1086
+ const fileCount = filesToCompile.length;
1087
+ let maxConcurrency;
1088
+ if (fileCount < 10) {
1089
+ maxConcurrency = Math.min(fileCount, cpuCount);
1090
+ }
1091
+ else if (fileCount < 50) {
1092
+ maxConcurrency = Math.min(cpuCount * 2, 12);
1093
+ }
1094
+ else {
1095
+ maxConcurrency = Math.min(cpuCount * 2, 16);
1096
+ }
1097
+ logger.info(`🚀 Compilando ${fileCount} archivos con concurrencia optimizada (${maxConcurrency} hilos)...`);
1098
+ await compileWithConcurrencyLimit(filesToCompile, maxConcurrency);
1099
+ // Guardar cache al final
1100
+ await saveCache();
1101
+ const endTime = Date.now();
1102
+ const elapsedTime = showTimingForHumans(endTime - startTime);
1103
+ logger.info(`⏱️ Tiempo total de compilación: ${elapsedTime}\n`); // Mostrar resumen de compilación
1104
+ await displayCompilationSummary(env.VERBOSE === 'true');
1105
+ }
1106
+ catch (error) {
1107
+ const errorMessage = error instanceof Error ? error.message : String(error);
1108
+ logger.error(`🚩 Error al compilar todos los archivos: ${errorMessage}`);
1109
+ // Registrar el error en el sistema unificado
1110
+ await handleCompilationError(error instanceof Error ? error : new Error(String(error)), 'compilación general', 'all', 'all', env.VERBOSE === 'true');
1111
+ // Mostrar resumen incluso si hay errores generales
1112
+ await displayCompilationSummary(env.VERBOSE === 'true');
1113
+ }
1114
+ }
1115
+ // Función wrapper para compatibilidad con tests
1116
+ export async function compileFile(filePath) {
1117
+ return await initCompile(filePath, true, 'individual');
1118
+ }
1119
+ export { WatchModeOptimizer };
1120
+ //# sourceMappingURL=compile.js.map