versacompiler 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +722 -722
- package/dist/compiler/compile-worker-pool.js +96 -0
- package/dist/compiler/compile-worker-thread.cjs +72 -0
- package/dist/compiler/compile.js +81 -2
- package/dist/compiler/integrity-validator.js +1 -1
- package/dist/compiler/module-resolution-optimizer.js +23 -20
- package/dist/compiler/performance-monitor.js +61 -61
- package/dist/compiler/pipeline/build-pipeline.js +127 -0
- package/dist/compiler/pipeline/core-plugins.js +218 -0
- package/dist/compiler/pipeline/module-graph.js +63 -0
- package/dist/compiler/pipeline/plugin-driver.js +87 -0
- package/dist/compiler/pipeline/types.js +2 -0
- package/dist/compiler/transforms.js +222 -16
- package/dist/compiler/typescript-manager.js +3 -1
- package/dist/compiler/typescript-sync-validator.js +33 -31
- package/dist/compiler/typescript-worker-pool.js +66 -19
- package/dist/compiler/typescript-worker-thread.cjs +482 -469
- package/dist/compiler/vuejs.js +32 -32
- package/dist/config.js +2 -0
- package/dist/hrm/VueHRM.js +359 -359
- package/dist/hrm/errorScreen.js +83 -83
- package/dist/hrm/getInstanciaVue.js +313 -313
- package/dist/hrm/initHRM.js +628 -586
- package/dist/main.js +2 -1
- package/dist/servicios/browserSync.js +8 -2
- package/dist/servicios/file-watcher.js +48 -6
- package/dist/servicios/readConfig.js +129 -54
- package/dist/servicios/versacompile.config.types.js +2 -0
- package/dist/utils/module-resolver.js +74 -40
- package/dist/utils/vue-types-setup.js +248 -248
- package/dist/wrappers/eslint-node.js +3 -1
- package/dist/wrappers/oxlint-node.js +3 -1
- package/package.json +73 -54
|
@@ -10,36 +10,36 @@ import * as typescript from 'typescript';
|
|
|
10
10
|
* Genera declaraciones básicas de tipos para Vue como fallback
|
|
11
11
|
*/
|
|
12
12
|
const generateBasicVueTypes = () => {
|
|
13
|
-
return `// Declaraciones básicas de tipos Vue para validación
|
|
14
|
-
declare global {
|
|
15
|
-
function ref<T>(value: T): { value: T };
|
|
16
|
-
function reactive<T extends object>(target: T): T;
|
|
17
|
-
function computed<T>(getter: () => T): { value: T };
|
|
18
|
-
function defineComponent<T>(options: T): T;
|
|
19
|
-
function defineProps<T = {}>(): T;
|
|
20
|
-
function defineEmits<T = {}>(): T;
|
|
21
|
-
function defineExpose<T = {}>(exposed: T): void;
|
|
22
|
-
function onMounted(fn: () => void): void;
|
|
23
|
-
function onUnmounted(fn: () => void): void;
|
|
24
|
-
function onBeforeMount(fn: () => void): void;
|
|
25
|
-
function onBeforeUnmount(fn: () => void): void;
|
|
26
|
-
function onUpdated(fn: () => void): void;
|
|
27
|
-
function onBeforeUpdate(fn: () => void): void;
|
|
28
|
-
function provide<T>(key: string | symbol, value: T): void;
|
|
29
|
-
function inject<T>(key: string | symbol, defaultValue?: T): T | undefined;
|
|
30
|
-
function useSlots(): { [key: string]: (...args: any[]) => any };
|
|
31
|
-
function useAttrs(): { [key: string]: any };
|
|
32
|
-
function useModel<T>(modelName?: string): { value: T };
|
|
33
|
-
function watch<T>(source: () => T, callback: (newValue: T, oldValue: T) => void): void;
|
|
34
|
-
function watchEffect(effect: () => void): void;
|
|
35
|
-
function nextTick(callback?: () => void): Promise<void>;
|
|
36
|
-
function getCurrentInstance(): any;
|
|
37
|
-
function mergeModels<T>(models: T): T;
|
|
38
|
-
}
|
|
39
|
-
declare module '*.vue' {
|
|
40
|
-
const component: any;
|
|
41
|
-
export default component;
|
|
42
|
-
}
|
|
13
|
+
return `// Declaraciones básicas de tipos Vue para validación
|
|
14
|
+
declare global {
|
|
15
|
+
function ref<T>(value: T): { value: T };
|
|
16
|
+
function reactive<T extends object>(target: T): T;
|
|
17
|
+
function computed<T>(getter: () => T): { value: T };
|
|
18
|
+
function defineComponent<T>(options: T): T;
|
|
19
|
+
function defineProps<T = {}>(): T;
|
|
20
|
+
function defineEmits<T = {}>(): T;
|
|
21
|
+
function defineExpose<T = {}>(exposed: T): void;
|
|
22
|
+
function onMounted(fn: () => void): void;
|
|
23
|
+
function onUnmounted(fn: () => void): void;
|
|
24
|
+
function onBeforeMount(fn: () => void): void;
|
|
25
|
+
function onBeforeUnmount(fn: () => void): void;
|
|
26
|
+
function onUpdated(fn: () => void): void;
|
|
27
|
+
function onBeforeUpdate(fn: () => void): void;
|
|
28
|
+
function provide<T>(key: string | symbol, value: T): void;
|
|
29
|
+
function inject<T>(key: string | symbol, defaultValue?: T): T | undefined;
|
|
30
|
+
function useSlots(): { [key: string]: (...args: any[]) => any };
|
|
31
|
+
function useAttrs(): { [key: string]: any };
|
|
32
|
+
function useModel<T>(modelName?: string): { value: T };
|
|
33
|
+
function watch<T>(source: () => T, callback: (newValue: T, oldValue: T) => void): void;
|
|
34
|
+
function watchEffect(effect: () => void): void;
|
|
35
|
+
function nextTick(callback?: () => void): Promise<void>;
|
|
36
|
+
function getCurrentInstance(): any;
|
|
37
|
+
function mergeModels<T>(models: T): T;
|
|
38
|
+
}
|
|
39
|
+
declare module '*.vue' {
|
|
40
|
+
const component: any;
|
|
41
|
+
export default component;
|
|
42
|
+
}
|
|
43
43
|
export {};`;
|
|
44
44
|
};
|
|
45
45
|
/**
|
|
@@ -269,7 +269,9 @@ export const validateTypesWithLanguageService = (fileName, content, compilerOpti
|
|
|
269
269
|
try {
|
|
270
270
|
languageService.dispose();
|
|
271
271
|
}
|
|
272
|
-
catch {
|
|
272
|
+
catch {
|
|
273
|
+
/* ignore dispose errors */
|
|
274
|
+
}
|
|
273
275
|
}
|
|
274
276
|
}
|
|
275
277
|
catch (error) {
|
|
@@ -19,8 +19,8 @@ export class TypeScriptWorkerPool {
|
|
|
19
19
|
workerPath;
|
|
20
20
|
initPromise = null;
|
|
21
21
|
isInitialized = false; // Configuración optimizada con reciclaje de workers
|
|
22
|
-
TASK_TIMEOUT =
|
|
23
|
-
WORKER_INIT_TIMEOUT =
|
|
22
|
+
TASK_TIMEOUT = 60000; // 60 segundos por tarea - workers son secuenciales, necesitan tiempo
|
|
23
|
+
WORKER_INIT_TIMEOUT = 10000; // 10 segundos para inicializar
|
|
24
24
|
MAX_TASKS_PER_WORKER = 200; // ✨ OPTIMIZADO: Aumentado de 50 a 200 para reducir overhead de reciclaje
|
|
25
25
|
WORKER_MEMORY_CHECK_INTERVAL = 500; // ✨ OPTIMIZADO: Verificar cada 500 tareas (reducir overhead)
|
|
26
26
|
// ✨ FIX #1: Referencias a timers para limpieza adecuada
|
|
@@ -28,7 +28,7 @@ export class TypeScriptWorkerPool {
|
|
|
28
28
|
cleanupInterval = null;
|
|
29
29
|
// Cola de tareas para cuando todos los workers están ocupados
|
|
30
30
|
taskQueue = [];
|
|
31
|
-
MAX_QUEUE_SIZE =
|
|
31
|
+
MAX_QUEUE_SIZE = 1000; // Suficiente para proyectos de 300+ archivos
|
|
32
32
|
// Flag para evitar concurrencia en ensureWorkerCapacity
|
|
33
33
|
isScalingUp = false;
|
|
34
34
|
// Métricas de rendimiento
|
|
@@ -85,8 +85,11 @@ export class TypeScriptWorkerPool {
|
|
|
85
85
|
// ✨ ISSUE #4: Obtener memoria real del worker
|
|
86
86
|
const memoryInfo = await this.getWorkerMemoryUsage(poolWorker);
|
|
87
87
|
poolWorker.memoryUsage = memoryInfo.heapUsed;
|
|
88
|
-
// Verificar límites de memoria y reciclaje automático
|
|
89
|
-
|
|
88
|
+
// Verificar límites de memoria y reciclaje automático.
|
|
89
|
+
// Solo reciclar workers INACTIVOS para evitar rechazar tareas en vuelo.
|
|
90
|
+
// Los workers con tareas pendientes se reciclan vía drainQueue cuando quedan libres.
|
|
91
|
+
const isIdle = !poolWorker.busy && poolWorker.pendingTasks.size === 0;
|
|
92
|
+
if (isIdle && this.shouldRecycleWorker(poolWorker)) {
|
|
90
93
|
const reason = this.getRecycleReason(poolWorker);
|
|
91
94
|
console.warn(`[WorkerPool] Worker ${poolWorker.id} requiere reciclaje: ${reason}`);
|
|
92
95
|
await this.recycleWorker(poolWorker);
|
|
@@ -198,8 +201,8 @@ export class TypeScriptWorkerPool {
|
|
|
198
201
|
const cpuCount = os.cpus().length;
|
|
199
202
|
switch (mode) {
|
|
200
203
|
case 'batch':
|
|
201
|
-
// Para modo batch, hasta
|
|
202
|
-
this.poolSize = Math.min(
|
|
204
|
+
// Para modo batch, hasta 4 workers para mejor rendimiento en proyectos grandes
|
|
205
|
+
this.poolSize = Math.min(4, Math.max(1, cpuCount - 1));
|
|
203
206
|
break;
|
|
204
207
|
case 'watch':
|
|
205
208
|
// Para modo watch, hasta 2 workers para menor impacto en sistema
|
|
@@ -376,9 +379,10 @@ export class TypeScriptWorkerPool {
|
|
|
376
379
|
});
|
|
377
380
|
}
|
|
378
381
|
else {
|
|
379
|
-
this.failedTasks++;
|
|
380
382
|
const errorMessage = response.error || 'Error desconocido del worker';
|
|
381
383
|
// ✨ FIX MEMORIA: Error simple sin referencias pesadas
|
|
384
|
+
// failedTasks se incrementa en el wrapper de queued.reject para tareas de cola,
|
|
385
|
+
// o en handleWorkerError/Exit para tareas directas que se re-encolan.
|
|
382
386
|
const error = new Error(errorMessage);
|
|
383
387
|
reject(error);
|
|
384
388
|
}
|
|
@@ -404,7 +408,8 @@ export class TypeScriptWorkerPool {
|
|
|
404
408
|
const pendingTasksArray = Array.from(poolWorker.pendingTasks.entries());
|
|
405
409
|
for (const [taskId, task] of pendingTasksArray) {
|
|
406
410
|
clearTimeout(task.timeout);
|
|
407
|
-
|
|
411
|
+
// failedTasks se contabiliza en el wrapper de queued.reject (para cola)
|
|
412
|
+
// o via re-encolado en typeCheck() catch (para tareas directas).
|
|
408
413
|
task.reject(new Error(`Worker ${poolWorker.id} failed`));
|
|
409
414
|
poolWorker.pendingTasks.delete(taskId);
|
|
410
415
|
}
|
|
@@ -436,6 +441,8 @@ export class TypeScriptWorkerPool {
|
|
|
436
441
|
if (index !== -1) {
|
|
437
442
|
this.workers[index] = newWorker;
|
|
438
443
|
}
|
|
444
|
+
// Drenar la cola con el nuevo worker para evitar tareas atascadas
|
|
445
|
+
setImmediate(() => this.drainAllWorkers());
|
|
439
446
|
}
|
|
440
447
|
catch {
|
|
441
448
|
// Silencioso
|
|
@@ -451,7 +458,8 @@ export class TypeScriptWorkerPool {
|
|
|
451
458
|
// 1. Rechazar tareas pendientes con cleanup
|
|
452
459
|
poolWorker.pendingTasks.forEach(task => {
|
|
453
460
|
clearTimeout(task.timeout);
|
|
454
|
-
|
|
461
|
+
// failedTasks se contabiliza en el wrapper de queued.reject (para cola)
|
|
462
|
+
// o via re-encolado en typeCheck() catch (para tareas directas).
|
|
455
463
|
task.reject(new Error(`Worker ${poolWorker.id} exited with code ${code}`));
|
|
456
464
|
});
|
|
457
465
|
poolWorker.pendingTasks.clear();
|
|
@@ -543,6 +551,8 @@ export class TypeScriptWorkerPool {
|
|
|
543
551
|
if (index !== -1) {
|
|
544
552
|
this.workers[index] = newWorker;
|
|
545
553
|
}
|
|
554
|
+
// Drenar la cola con el nuevo worker listo
|
|
555
|
+
setImmediate(() => this.drainQueue(newWorker));
|
|
546
556
|
}
|
|
547
557
|
catch (error) {
|
|
548
558
|
console.error(`[WorkerPool] Error reciclando worker ${poolWorker.id}:`, error);
|
|
@@ -573,6 +583,18 @@ export class TypeScriptWorkerPool {
|
|
|
573
583
|
}
|
|
574
584
|
return null; // Todos los workers están muy ocupados
|
|
575
585
|
}
|
|
586
|
+
/**
|
|
587
|
+
* Drena la cola en todos los workers disponibles
|
|
588
|
+
*/
|
|
589
|
+
drainAllWorkers() {
|
|
590
|
+
for (const worker of this.workers) {
|
|
591
|
+
if (!worker.busy && worker.pendingTasks.size === 0) {
|
|
592
|
+
this.drainQueue(worker);
|
|
593
|
+
if (this.taskQueue.length === 0)
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
576
598
|
/**
|
|
577
599
|
* Procesa la siguiente tarea de la cola en el worker liberado
|
|
578
600
|
*/
|
|
@@ -581,19 +603,27 @@ export class TypeScriptWorkerPool {
|
|
|
581
603
|
return;
|
|
582
604
|
if (poolWorker.busy || poolWorker.pendingTasks.size > 0)
|
|
583
605
|
return;
|
|
584
|
-
|
|
606
|
+
// Si el worker alcanzó el límite de tareas, reciclarlo y luego drenar
|
|
607
|
+
if (poolWorker.taskCounter >= this.MAX_TASKS_PER_WORKER) {
|
|
608
|
+
this.recycleWorker(poolWorker)
|
|
609
|
+
.then(() => setImmediate(() => this.drainAllWorkers()))
|
|
610
|
+
.catch(() => { });
|
|
585
611
|
return;
|
|
612
|
+
}
|
|
586
613
|
const queued = this.taskQueue.shift();
|
|
587
614
|
if (!queued)
|
|
588
615
|
return;
|
|
589
616
|
const waitMs = Date.now() - queued.queuedAt;
|
|
590
617
|
if (waitMs > 30000) {
|
|
618
|
+
// queued.reject incluye failedTasks++ en el wrapper (ver typeCheck())
|
|
591
619
|
queued.reject(new Error(`Queue task expired after ${waitMs}ms`));
|
|
620
|
+
// Continuar drenando la cola con la siguiente tarea
|
|
621
|
+
setImmediate(() => this.drainQueue(poolWorker));
|
|
592
622
|
return;
|
|
593
623
|
}
|
|
594
624
|
this.typeCheckWithWorker(poolWorker, queued.fileName, queued.content, queued.compilerOptions)
|
|
595
625
|
.then(queued.resolve)
|
|
596
|
-
.catch(queued.reject);
|
|
626
|
+
.catch(queued.reject); // queued.reject incluye failedTasks++ en el wrapper
|
|
597
627
|
}
|
|
598
628
|
/**
|
|
599
629
|
* Realiza type checking usando el pool de workers
|
|
@@ -613,23 +643,38 @@ export class TypeScriptWorkerPool {
|
|
|
613
643
|
return await this.typeCheckWithWorker(availableWorker, fileName, content, compilerOptions);
|
|
614
644
|
}
|
|
615
645
|
catch {
|
|
616
|
-
// Worker
|
|
646
|
+
// Worker falló o llegó al límite de tareas
|
|
647
|
+
// Si alcanzó el límite, disparar reciclaje inmediato
|
|
648
|
+
if (availableWorker.taskCounter >= this.MAX_TASKS_PER_WORKER) {
|
|
649
|
+
this.recycleWorker(availableWorker)
|
|
650
|
+
.then(() => setImmediate(() => this.drainAllWorkers()))
|
|
651
|
+
.catch(() => { });
|
|
652
|
+
}
|
|
617
653
|
}
|
|
618
654
|
}
|
|
619
655
|
// Ningún worker disponible: encolar la tarea
|
|
620
656
|
if (this.taskQueue.length >= this.MAX_QUEUE_SIZE) {
|
|
621
|
-
// Cola llena →
|
|
622
|
-
|
|
657
|
+
// Cola llena → omitir type check para no bloquear el event loop
|
|
658
|
+
// (con MAX_QUEUE_SIZE=1000 esto solo ocurre en proyectos extremadamente grandes)
|
|
659
|
+
console.warn(`[TypeCheckQueue] Cola llena (${this.MAX_QUEUE_SIZE} tareas). Type check omitido para: ${path.basename(fileName)}`);
|
|
660
|
+
this.completedTasks++; // Contabilizar como completado para mantener métricas consistentes
|
|
661
|
+
return { diagnostics: [], hasErrors: false };
|
|
623
662
|
}
|
|
624
663
|
// Escalar el pool si es posible
|
|
625
664
|
this.ensureWorkerCapacity().catch(() => { });
|
|
626
665
|
return new Promise((resolve, reject) => {
|
|
666
|
+
// Wrapper para reject que garantiza que failedTasks se incrementa exactamente una vez
|
|
667
|
+
// para todas las tareas que pasan por la cola (drainQueue path).
|
|
668
|
+
const wrappedReject = (err) => {
|
|
669
|
+
this.failedTasks++;
|
|
670
|
+
reject(err);
|
|
671
|
+
};
|
|
627
672
|
this.taskQueue.push({
|
|
628
673
|
fileName,
|
|
629
674
|
content,
|
|
630
675
|
compilerOptions,
|
|
631
676
|
resolve,
|
|
632
|
-
reject,
|
|
677
|
+
reject: wrappedReject,
|
|
633
678
|
queuedAt: Date.now(),
|
|
634
679
|
});
|
|
635
680
|
});
|
|
@@ -639,9 +684,9 @@ export class TypeScriptWorkerPool {
|
|
|
639
684
|
* ✨ FIX MEMORIA: Optimizado para prevenir fugas de memoria
|
|
640
685
|
*/
|
|
641
686
|
async typeCheckWithWorker(poolWorker, fileName, content, compilerOptions) {
|
|
642
|
-
// Si el worker alcanzó su límite de tareas,
|
|
687
|
+
// Si el worker alcanzó su límite de tareas, encolar para reciclaje
|
|
643
688
|
if (poolWorker.taskCounter >= this.MAX_TASKS_PER_WORKER) {
|
|
644
|
-
|
|
689
|
+
throw new Error(`Worker ${poolWorker.id} ha alcanzado el límite de tareas`);
|
|
645
690
|
}
|
|
646
691
|
return new Promise((resolve, reject) => {
|
|
647
692
|
const taskId = `task-${poolWorker.id}-${++poolWorker.taskCounter}-${Date.now()}`;
|
|
@@ -660,6 +705,8 @@ export class TypeScriptWorkerPool {
|
|
|
660
705
|
poolWorker.busy = false;
|
|
661
706
|
}
|
|
662
707
|
reject(new Error(`Timeout (${dynamicTimeout}ms) en type checking para ${fileName}`));
|
|
708
|
+
// Drenar la cola cuando se libera la tarea por timeout
|
|
709
|
+
setImmediate(() => this.drainQueue(poolWorker));
|
|
663
710
|
}
|
|
664
711
|
}, dynamicTimeout);
|
|
665
712
|
// ✨ FIX MEMORIA: Wrapper para resolver/rechazar que limpia el timeout
|
|
@@ -764,7 +811,7 @@ export class TypeScriptWorkerPool {
|
|
|
764
811
|
complexityMultiplier = Math.min(complexityMultiplier, 5); // Máximo 5x el timeout base
|
|
765
812
|
complexityMultiplier = Math.max(complexityMultiplier, 0.5); // Mínimo 0.5x el timeout base
|
|
766
813
|
const finalTimeout = Math.round(baseTimeout * complexityMultiplier);
|
|
767
|
-
return Math.min(finalTimeout,
|
|
814
|
+
return Math.min(finalTimeout, 120000); // Máximo absoluto de 120 segundos
|
|
768
815
|
}
|
|
769
816
|
/**
|
|
770
817
|
* Fallback síncrono para type checking
|