versacompiler 2.4.1 → 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.
Files changed (32) hide show
  1. package/README.md +722 -722
  2. package/dist/compiler/compile-worker-pool.js +96 -0
  3. package/dist/compiler/compile-worker-thread.cjs +72 -0
  4. package/dist/compiler/compile.js +81 -2
  5. package/dist/compiler/integrity-validator.js +1 -1
  6. package/dist/compiler/module-resolution-optimizer.js +23 -20
  7. package/dist/compiler/performance-monitor.js +61 -61
  8. package/dist/compiler/pipeline/build-pipeline.js +127 -0
  9. package/dist/compiler/pipeline/core-plugins.js +218 -0
  10. package/dist/compiler/pipeline/module-graph.js +63 -0
  11. package/dist/compiler/pipeline/plugin-driver.js +87 -0
  12. package/dist/compiler/pipeline/types.js +2 -0
  13. package/dist/compiler/transforms.js +222 -16
  14. package/dist/compiler/typescript-manager.js +3 -1
  15. package/dist/compiler/typescript-sync-validator.js +33 -31
  16. package/dist/compiler/typescript-worker-thread.cjs +482 -475
  17. package/dist/compiler/vuejs.js +32 -32
  18. package/dist/config.js +2 -0
  19. package/dist/hrm/VueHRM.js +359 -359
  20. package/dist/hrm/errorScreen.js +83 -83
  21. package/dist/hrm/getInstanciaVue.js +313 -313
  22. package/dist/hrm/initHRM.js +628 -586
  23. package/dist/main.js +2 -1
  24. package/dist/servicios/browserSync.js +8 -2
  25. package/dist/servicios/file-watcher.js +48 -6
  26. package/dist/servicios/readConfig.js +129 -54
  27. package/dist/servicios/versacompile.config.types.js +2 -0
  28. package/dist/utils/module-resolver.js +74 -40
  29. package/dist/utils/vue-types-setup.js +248 -248
  30. package/dist/wrappers/eslint-node.js +3 -1
  31. package/dist/wrappers/oxlint-node.js +3 -1
  32. package/package.json +72 -53
@@ -0,0 +1,96 @@
1
+ import * as os from 'node:os';
2
+ import * as path from 'node:path';
3
+ import * as process from 'node:process';
4
+ import { Worker } from 'node:worker_threads';
5
+ export class CompileWorkerPool {
6
+ static instance;
7
+ workers = [];
8
+ pending = new Map();
9
+ queue = [];
10
+ poolSize;
11
+ workerPath;
12
+ TASK_TIMEOUT = 60000;
13
+ constructor() {
14
+ const cpuCount = os.cpus().length;
15
+ const configuredMax = parseInt(process.env.COMPILE_MAX_WORKERS || '2', 10);
16
+ this.poolSize = Math.min(configuredMax, Math.max(1, cpuCount - 1));
17
+ this.workerPath = path.join(process.env.PATH_PROY || path.join(process.cwd(), 'src'), 'compiler', 'compile-worker-thread.cjs');
18
+ this.initWorkers();
19
+ }
20
+ static getInstance() {
21
+ if (!CompileWorkerPool.instance) {
22
+ CompileWorkerPool.instance = new CompileWorkerPool();
23
+ }
24
+ return CompileWorkerPool.instance;
25
+ }
26
+ initWorkers() {
27
+ for (let i = 0; i < this.poolSize; i++) {
28
+ const worker = new Worker(this.workerPath, {
29
+ env: process.env,
30
+ });
31
+ const poolWorker = { worker, busy: false };
32
+ worker.on('message', (response) => {
33
+ const pending = this.pending.get(response.id);
34
+ if (!pending)
35
+ return;
36
+ clearTimeout(pending.timeout);
37
+ this.pending.delete(response.id);
38
+ poolWorker.busy = false;
39
+ if (!response.success) {
40
+ pending.reject(new Error(response.error || 'Worker task failed'));
41
+ }
42
+ else {
43
+ pending.resolve(response.data);
44
+ }
45
+ this.drainQueue();
46
+ });
47
+ worker.on('error', error => {
48
+ poolWorker.busy = false;
49
+ for (const [id, pending] of this.pending) {
50
+ clearTimeout(pending.timeout);
51
+ const normalized = error instanceof Error
52
+ ? error
53
+ : new Error(String(error));
54
+ pending.reject(normalized);
55
+ this.pending.delete(id);
56
+ }
57
+ this.drainQueue();
58
+ });
59
+ this.workers.push(poolWorker);
60
+ }
61
+ }
62
+ async runTask(type, payload) {
63
+ const id = `${type}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
64
+ const message = { id, type, payload };
65
+ return new Promise((resolve, reject) => {
66
+ const timeout = setTimeout(() => {
67
+ this.pending.delete(id);
68
+ reject(new Error(`Worker timeout: ${type}`));
69
+ }, this.TASK_TIMEOUT);
70
+ this.pending.set(id, { resolve, reject, timeout });
71
+ const worker = this.getAvailableWorker();
72
+ if (worker) {
73
+ worker.busy = true;
74
+ worker.worker.postMessage(message);
75
+ return;
76
+ }
77
+ this.queue.push(message);
78
+ });
79
+ }
80
+ getAvailableWorker() {
81
+ return this.workers.find(worker => !worker.busy) || null;
82
+ }
83
+ drainQueue() {
84
+ if (this.queue.length === 0)
85
+ return;
86
+ const worker = this.getAvailableWorker();
87
+ if (!worker)
88
+ return;
89
+ const message = this.queue.shift();
90
+ if (!message)
91
+ return;
92
+ worker.busy = true;
93
+ worker.worker.postMessage(message);
94
+ }
95
+ }
96
+ //# sourceMappingURL=compile-worker-pool.js.map
@@ -0,0 +1,72 @@
1
+ const { parentPort } = require('node:worker_threads');
2
+
3
+ let preCompileVue;
4
+ let preCompileTS;
5
+ let minifyJS;
6
+
7
+ async function loadVue() {
8
+ if (!preCompileVue) {
9
+ const mod = await import('./vuejs.js');
10
+ preCompileVue = mod.preCompileVue;
11
+ }
12
+ return preCompileVue;
13
+ }
14
+
15
+ async function loadTypeScript() {
16
+ if (!preCompileTS) {
17
+ const mod = await import('./typescript-manager.js');
18
+ preCompileTS = mod.preCompileTS;
19
+ }
20
+ return preCompileTS;
21
+ }
22
+
23
+ async function loadMinify() {
24
+ if (!minifyJS) {
25
+ const mod = await import('./minify.js');
26
+ minifyJS = mod.minifyJS;
27
+ }
28
+ return minifyJS;
29
+ }
30
+
31
+ parentPort.on('message', async message => {
32
+ const { id, type, payload } = message;
33
+ try {
34
+ if (type === 'vue') {
35
+ const compileVue = await loadVue();
36
+ const result = await compileVue(
37
+ payload.source,
38
+ payload.fileName,
39
+ payload.isProd === true,
40
+ );
41
+ parentPort.postMessage({ id, success: true, data: result });
42
+ return;
43
+ }
44
+ if (type === 'ts') {
45
+ const compileTS = await loadTypeScript();
46
+ const result = await compileTS(
47
+ payload.source,
48
+ payload.fileName,
49
+ payload.scriptInfo,
50
+ );
51
+ parentPort.postMessage({ id, success: true, data: result });
52
+ return;
53
+ }
54
+ if (type === 'minify') {
55
+ const minify = await loadMinify();
56
+ const result = await minify(payload.source, payload.fileName, true);
57
+ parentPort.postMessage({ id, success: true, data: result });
58
+ return;
59
+ }
60
+ parentPort.postMessage({
61
+ id,
62
+ success: false,
63
+ error: `Tipo de tarea desconocido: ${type}`,
64
+ });
65
+ } catch (error) {
66
+ parentPort.postMessage({
67
+ id,
68
+ success: false,
69
+ error: error instanceof Error ? error.message : String(error),
70
+ });
71
+ }
72
+ });
@@ -6,9 +6,12 @@ import * as process from 'node:process';
6
6
  const { argv, cwd, env } = process;
7
7
  // Lazy loading optimizations - Only import lightweight modules synchronously
8
8
  import { logger, setProgressManagerGetter } from '../servicios/logger.js';
9
+ import { getLoadedConfig } from '../servicios/readConfig.js';
9
10
  import { promptUser } from '../utils/promptUser.js';
10
11
  import { showTimingForHumans } from '../utils/utils.js';
11
12
  import { integrityValidator } from './integrity-validator.js';
13
+ import { BuildPipeline } from './pipeline/build-pipeline.js';
14
+ import { createCorePlugins } from './pipeline/core-plugins.js';
12
15
  // Configurar el getter del ProgressManager para el logger
13
16
  setProgressManagerGetter(() => ProgressManager.getInstance());
14
17
  /**
@@ -29,6 +32,7 @@ let generateTailwindCSS;
29
32
  let estandarizaCode;
30
33
  let preCompileTS;
31
34
  let preCompileVue;
35
+ let pipelineInstance = null;
32
36
  // 🚀 Importar optimizador de transformaciones
33
37
  let TransformOptimizer;
34
38
  // 🚀 Importar optimizador de resolución de módulos
@@ -544,6 +548,16 @@ class SmartCompilationCache {
544
548
  catch {
545
549
  // Ignorar si no existe package-lock.json
546
550
  }
551
+ // 2b. Hash de pnpm-lock.yaml si existe (pnpm)
552
+ try {
553
+ const pnpmLockPath = path.join(cwd(), 'pnpm-lock.yaml');
554
+ const pnpmLockContent = await readFile(pnpmLockPath, 'utf8');
555
+ hash.update(`pnpm-lock:${pnpmLockContent.length}`);
556
+ hash.update(pnpmLockContent);
557
+ }
558
+ catch {
559
+ // Ignorar si no existe pnpm-lock.yaml
560
+ }
547
561
  // 3. ✨ NUEVO: Hash de timestamps críticos de node_modules
548
562
  try {
549
563
  const nodeModulesPath = path.join(cwd(), 'node_modules');
@@ -609,7 +623,7 @@ class SmartCompilationCache {
609
623
  return false;
610
624
  try {
611
625
  // Ejecutar todas las verificaciones independientes en paralelo
612
- const [currentContentHash, currentDependencyHash, fileStat, _outputStat] = await Promise.all([
626
+ const [currentContentHash, currentDependencyHash, fileStat, _outputStat,] = await Promise.all([
613
627
  this.generateContentHash(filePath),
614
628
  this.generateDependencyHash(),
615
629
  stat(filePath),
@@ -1406,7 +1420,8 @@ async function _displaySingleLinterError(error, filePath) {
1406
1420
  }
1407
1421
  else {
1408
1422
  // Líneas de contexto
1409
- logger.info(chalkLib.blue(` ${prefix} │ `) + chalkLib.gray(currentLine));
1423
+ logger.info(chalkLib.blue(` ${prefix} │ `) +
1424
+ chalkLib.gray(currentLine));
1410
1425
  }
1411
1426
  }
1412
1427
  logger.info(chalkLib.blue(' ╰────'));
@@ -1558,6 +1573,67 @@ class WatchModeOptimizer {
1558
1573
  this.fileSystemCache.clear();
1559
1574
  }
1560
1575
  }
1576
+ function getBuildPipeline() {
1577
+ if (!pipelineInstance) {
1578
+ const basePlugins = createCorePlugins();
1579
+ const config = getLoadedConfig();
1580
+ const userPlugins = normalizeUserPlugins(config?.plugins);
1581
+ pipelineInstance = new BuildPipeline([...basePlugins, ...userPlugins]);
1582
+ }
1583
+ return pipelineInstance;
1584
+ }
1585
+ function normalizeUserPlugins(plugins) {
1586
+ if (!plugins || !Array.isArray(plugins))
1587
+ return [];
1588
+ return plugins.filter((plugin) => {
1589
+ if (!plugin || typeof plugin !== 'object')
1590
+ return false;
1591
+ const candidate = plugin;
1592
+ if (!candidate.name || typeof candidate.name !== 'string')
1593
+ return false;
1594
+ return Boolean(candidate.onResolve ||
1595
+ candidate.onLoad ||
1596
+ candidate.onTransform ||
1597
+ candidate.onHotUpdate ||
1598
+ candidate.onEnd);
1599
+ });
1600
+ }
1601
+ export function getPipelineModuleGraph() {
1602
+ if (env.PIPELINE_V2 === 'false')
1603
+ return null;
1604
+ return getBuildPipeline().getModuleGraph();
1605
+ }
1606
+ export async function runPipelineHotUpdate(filePath, type) {
1607
+ if (env.PIPELINE_V2 === 'false') {
1608
+ return { reload: 'none' };
1609
+ }
1610
+ return getBuildPipeline().hotUpdate({ path: filePath, type });
1611
+ }
1612
+ async function compileWithPipeline(inPath, outPath, mode = 'individual') {
1613
+ const pipeline = getBuildPipeline();
1614
+ const result = await pipeline.compileFile(inPath);
1615
+ if (result.errors.length > 0) {
1616
+ for (const message of result.errors) {
1617
+ await handleCompilationError(new Error(message), inPath, 'pipeline', mode, env.VERBOSE === 'true');
1618
+ }
1619
+ throw new Error(result.errors[0]);
1620
+ }
1621
+ if (!result.code || result.code.trim().length === 0) {
1622
+ await handleCompilationError(new Error('El código compilado está vacío.'), inPath, 'pipeline', mode, env.VERBOSE === 'true');
1623
+ throw new Error('El código compilado está vacío.');
1624
+ }
1625
+ const destinationDir = path.dirname(outPath);
1626
+ await mkdir(destinationDir, { recursive: true });
1627
+ await writeFile(outPath, result.code, 'utf-8');
1628
+ if (result.dependencies.length > 0) {
1629
+ smartCache.registerDependencies(inPath, result.dependencies);
1630
+ }
1631
+ registerCompilationSuccess(inPath, 'pipeline');
1632
+ return {
1633
+ error: null,
1634
+ action: 'extension',
1635
+ };
1636
+ }
1561
1637
  async function compileJS(inPath, outPath, mode = 'individual') {
1562
1638
  const timings = {};
1563
1639
  // Si la ruta ya es absoluta, no la resolvamos de nuevo
@@ -1565,6 +1641,9 @@ async function compileJS(inPath, outPath, mode = 'individual') {
1565
1641
  ? normalizeRuta(inPath)
1566
1642
  : normalizeRuta(path.resolve(inPath)); // 🚀 Usar OptimizedModuleManager para carga optimizada
1567
1643
  const moduleManager = OptimizedModuleManager.getInstance();
1644
+ if (env.PIPELINE_V2 !== 'false') {
1645
+ return compileWithPipeline(inPath, outPath, mode);
1646
+ }
1568
1647
  // Timing de lectura
1569
1648
  let start = Date.now();
1570
1649
  const extension = path.extname(inPath); // Asegurar que el parser esté cargado
@@ -48,7 +48,7 @@ export class IntegrityValidator {
48
48
  // Revisar cache
49
49
  const cacheKey = this.getCacheKey(context, processed);
50
50
  const cached = this.cache.get(cacheKey);
51
- if (cached && (Date.now() - cached.timestamp) < this.CACHE_TTL) {
51
+ if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
52
52
  this.stats.cacheHits++;
53
53
  if (options.verbose) {
54
54
  logger.info(`[IntegrityValidator] Cache hit for ${context}`);
@@ -14,6 +14,7 @@ import { dirname, join, relative } from 'node:path';
14
14
  import { cwd, env } from 'node:process';
15
15
  import { logger } from '../servicios/logger.js';
16
16
  import { EXCLUDED_MODULES } from '../utils/excluded-modules.js';
17
+ import { parseModuleSpecifier, resolveExportValue, } from '../utils/module-resolver.js';
17
18
  /**
18
19
  * Sistema de optimización de resolución de módulos
19
20
  * Implementa indexación, caché y búsquedas O(1)
@@ -122,7 +123,7 @@ export class ModuleResolutionOptimizer {
122
123
  for (const entry of entries) {
123
124
  const modulePath = join(nodeModulesPath, entry);
124
125
  try {
125
- if (entry.startsWith('/dist/examples')) {
126
+ if (entry.startsWith('/dist')) {
126
127
  // Scoped packages
127
128
  const scopedModules = readdirSync(modulePath);
128
129
  this.metrics.filesystemAccess++;
@@ -207,10 +208,7 @@ export class ModuleResolutionOptimizer {
207
208
  entryPoint = dotExport;
208
209
  }
209
210
  else if (typeof dotExport === 'object') {
210
- entryPoint =
211
- dotExport.import ||
212
- dotExport.browser ||
213
- dotExport.default;
211
+ entryPoint = resolveExportValue(dotExport);
214
212
  }
215
213
  }
216
214
  }
@@ -420,7 +418,9 @@ export class ModuleResolutionOptimizer {
420
418
  this.aliasIndex = [];
421
419
  // Convertir alias a índice con prioridad
422
420
  for (const [alias, target] of Object.entries(pathAlias)) {
423
- const pattern = alias.replace('/*', '');
421
+ // Quitar solo el '*' final para conservar el separador '/'
422
+ // Ejemplo: '@/*' → '@/', así '@vueuse/core' no hace match pero '@/foo' sí
423
+ const pattern = alias.replace('*', '');
424
424
  const priority = pattern.length; // Patrones más largos tienen prioridad
425
425
  // El regex debe coincidir con el patrón al inicio, seguido de cualquier cosa o fin de cadena
426
426
  // Por ejemplo, para "@/" debe coincidir con "@/cualquier-cosa" o solo "@/"
@@ -453,6 +453,7 @@ export class ModuleResolutionOptimizer {
453
453
  path: null,
454
454
  cached: false,
455
455
  resolveTime: performance.now() - startTime,
456
+ excluded: true,
456
457
  };
457
458
  }
458
459
  // Crear clave de caché
@@ -472,13 +473,16 @@ export class ModuleResolutionOptimizer {
472
473
  // Resolver módulo
473
474
  let resolvedPath = null;
474
475
  try {
475
- // 1. Verificar si es subpath de módulo (ej: 'vue/dist/vue.esm-bundler')
476
- if (moduleName.includes('/')) {
476
+ // 1. Parse specifier to correctly handle scoped packages
477
+ const { packageName, subPath } = parseModuleSpecifier(moduleName);
478
+ if (subPath) {
479
+ // Has a real subpath (e.g. 'vue/dist/x' or '@scope/pkg/sub')
477
480
  resolvedPath = await this.resolveSubPath(moduleName);
478
481
  }
479
482
  else {
483
+ // Direct package (e.g. 'vue' or '@vueuse/core')
480
484
  // 2. Búsqueda O(1) en el índice
481
- resolvedPath = this.resolveFromIndex(moduleName);
485
+ resolvedPath = this.resolveFromIndex(packageName);
482
486
  }
483
487
  // 3. Si no se encuentra en índice, intentar resolución tradicional
484
488
  if (!resolvedPath) {
@@ -521,8 +525,7 @@ export class ModuleResolutionOptimizer {
521
525
  * Resuelve subpaths de módulos (ej: 'vue/dist/vue.esm-bundler')
522
526
  */
523
527
  async resolveSubPath(moduleName) {
524
- const [packageName, ...subPathParts] = moduleName.split('/');
525
- const subPath = subPathParts.join('/');
528
+ const { packageName, subPath } = parseModuleSpecifier(moduleName);
526
529
  if (!packageName) {
527
530
  return null;
528
531
  }
@@ -531,19 +534,19 @@ export class ModuleResolutionOptimizer {
531
534
  if (!moduleInfo) {
532
535
  return null;
533
536
  }
537
+ // If no subPath, resolve as direct package
538
+ if (!subPath) {
539
+ const entryPoint = moduleInfo.optimizedEntry || moduleInfo.entryPoint;
540
+ return join(moduleInfo.fullPath, entryPoint);
541
+ }
534
542
  // Verificar exports field para subpaths
535
543
  if (moduleInfo.hasExports && moduleInfo.packageJson.exports) {
536
544
  const exportKey = `./${subPath}`;
537
545
  const exportPath = moduleInfo.packageJson.exports[exportKey];
538
546
  if (exportPath) {
539
- if (typeof exportPath === 'string') {
540
- return join(moduleInfo.fullPath, exportPath);
541
- }
542
- else if (typeof exportPath === 'object') {
543
- const importPath = exportPath.import || exportPath.default;
544
- if (typeof importPath === 'string') {
545
- return join(moduleInfo.fullPath, importPath);
546
- }
547
+ const resolved = resolveExportValue(exportPath);
548
+ if (resolved) {
549
+ return join(moduleInfo.fullPath, resolved);
547
550
  }
548
551
  }
549
552
  }
@@ -872,7 +875,7 @@ export class ModuleResolutionOptimizer {
872
875
  export async function getOptimizedModulePath(moduleName, fromFile) {
873
876
  const optimizer = ModuleResolutionOptimizer.getInstance();
874
877
  const result = await optimizer.resolveModule(moduleName, fromFile);
875
- return result.path;
878
+ return { path: result.path, excluded: result.excluded === true };
876
879
  }
877
880
  export function getOptimizedAliasPath(path) {
878
881
  const optimizer = ModuleResolutionOptimizer.getInstance();
@@ -85,67 +85,67 @@ export class PerformanceMonitor {
85
85
  const i = Math.floor(Math.log(bytes) / Math.log(k));
86
86
  return (parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]);
87
87
  };
88
- const report = `
89
- 🚀 VERSACOMPILER PERFORMANCE REPORT
90
- =====================================
91
-
92
- 📊 RESUMEN GENERAL
93
- Hit Rate Total: ${stats.summary.overallHitRate}%
94
- Cache Hits: ${stats.summary.totalCacheHits}
95
- Cache Misses: ${stats.summary.totalCacheMisses}
96
- Memoria Total: ${formatBytes(stats.summary.totalMemoryUsage)}
97
- Entradas Cache: ${stats.summary.totalCacheEntries}
98
-
99
- 🎯 VUE HMR CACHE
100
- Size: ${stats.vueHMRCache.size}/${stats.vueHMRCache.maxSize}
101
- TTL: ${Math.round(stats.vueHMRCache.ttl / 1000 / 60)}min
102
-
103
- 📝 PARSER AST CACHE
104
- Hit Rate: ${stats.parserCache.hitRate}%
105
- Cache Hits: ${stats.parserCache.cacheHits}
106
- Cache Misses: ${stats.parserCache.cacheMisses}
107
- Size: ${stats.parserCache.cacheSize}/${stats.parserCache.maxCacheSize}
108
- Memoria: ${formatBytes(stats.parserCache.memoryUsage)}/${formatBytes(stats.parserCache.maxMemoryUsage)}
109
-
110
- 📖 FILE CONTENT CACHE
111
- Hit Rate: ${stats.fileContentCache.hitRate}%
112
- Cache Hits: ${stats.fileContentCache.cacheHits}
113
- Cache Misses: ${stats.fileContentCache.cacheMisses}
114
- Size: ${stats.fileContentCache.cacheSize}/${stats.fileContentCache.maxCacheSize}
115
-
116
- 🌐 BROWSERSYNC FILE CACHE
117
- Hit Rate: ${stats.browserSyncCache.hitRate}%
118
- Cache Hits: ${stats.browserSyncCache.cacheHits}
119
- Cache Misses: ${stats.browserSyncCache.cacheMisses}
120
- Size: ${stats.browserSyncCache.cacheSize}/${stats.browserSyncCache.maxCacheSize}
121
- Memoria: ${formatBytes(stats.browserSyncCache.memoryUsage)}/${formatBytes(stats.browserSyncCache.maxMemoryUsage)}
122
-
123
- 🗜️ MINIFICATION CACHE
124
- Hit Rate: ${stats.minificationCache.hitRate}%
125
- Cache Hits: ${stats.minificationCache.cacheHits}
126
- Cache Misses: ${stats.minificationCache.cacheMisses}
127
- Size: ${stats.minificationCache.cacheSize}/${stats.minificationCache.maxCacheSize}
128
- Memoria: ${formatBytes(stats.minificationCache.memoryUsage)}/${formatBytes(stats.minificationCache.maxMemoryUsage)}
129
- Compresión Promedio: ${stats.minificationCache.avgCompressionRatio}%
130
-
131
- 🔄 TRANSFORM OPTIMIZER
132
- Hit Rate: ${stats.transformOptimizer.hitRate}%
133
- Cache Hits: ${stats.transformOptimizer.cacheHits}
134
- Cache Misses: ${stats.transformOptimizer.cacheMisses}
135
- Transformaciones: ${stats.transformOptimizer.totalTransforms}
136
- Size: ${stats.transformOptimizer.cacheSize}
137
- Memoria: ${formatBytes(stats.transformOptimizer.memoryUsage)}
138
-
139
- 📦 MODULE RESOLUTION
140
- Hit Rate: ${stats.moduleResolution.cacheHitRate?.toFixed(1)}%
141
- Cache Hits: ${stats.moduleResolution.cacheHits}
142
- Cache Misses: ${stats.moduleResolution.cacheMisses}
143
- Resoluciones: ${stats.moduleResolution.totalResolutions}
144
- Índice Módulos: ${stats.moduleResolution.moduleIndexSize}
145
- Índice Alias: ${stats.moduleResolution.aliasIndexSize}
146
- Tiempo Promedio: ${stats.moduleResolution.averageResolveTime?.toFixed(2)}ms
147
-
148
- =====================================
88
+ const report = `
89
+ 🚀 VERSACOMPILER PERFORMANCE REPORT
90
+ =====================================
91
+
92
+ 📊 RESUMEN GENERAL
93
+ Hit Rate Total: ${stats.summary.overallHitRate}%
94
+ Cache Hits: ${stats.summary.totalCacheHits}
95
+ Cache Misses: ${stats.summary.totalCacheMisses}
96
+ Memoria Total: ${formatBytes(stats.summary.totalMemoryUsage)}
97
+ Entradas Cache: ${stats.summary.totalCacheEntries}
98
+
99
+ 🎯 VUE HMR CACHE
100
+ Size: ${stats.vueHMRCache.size}/${stats.vueHMRCache.maxSize}
101
+ TTL: ${Math.round(stats.vueHMRCache.ttl / 1000 / 60)}min
102
+
103
+ 📝 PARSER AST CACHE
104
+ Hit Rate: ${stats.parserCache.hitRate}%
105
+ Cache Hits: ${stats.parserCache.cacheHits}
106
+ Cache Misses: ${stats.parserCache.cacheMisses}
107
+ Size: ${stats.parserCache.cacheSize}/${stats.parserCache.maxCacheSize}
108
+ Memoria: ${formatBytes(stats.parserCache.memoryUsage)}/${formatBytes(stats.parserCache.maxMemoryUsage)}
109
+
110
+ 📖 FILE CONTENT CACHE
111
+ Hit Rate: ${stats.fileContentCache.hitRate}%
112
+ Cache Hits: ${stats.fileContentCache.cacheHits}
113
+ Cache Misses: ${stats.fileContentCache.cacheMisses}
114
+ Size: ${stats.fileContentCache.cacheSize}/${stats.fileContentCache.maxCacheSize}
115
+
116
+ 🌐 BROWSERSYNC FILE CACHE
117
+ Hit Rate: ${stats.browserSyncCache.hitRate}%
118
+ Cache Hits: ${stats.browserSyncCache.cacheHits}
119
+ Cache Misses: ${stats.browserSyncCache.cacheMisses}
120
+ Size: ${stats.browserSyncCache.cacheSize}/${stats.browserSyncCache.maxCacheSize}
121
+ Memoria: ${formatBytes(stats.browserSyncCache.memoryUsage)}/${formatBytes(stats.browserSyncCache.maxMemoryUsage)}
122
+
123
+ 🗜️ MINIFICATION CACHE
124
+ Hit Rate: ${stats.minificationCache.hitRate}%
125
+ Cache Hits: ${stats.minificationCache.cacheHits}
126
+ Cache Misses: ${stats.minificationCache.cacheMisses}
127
+ Size: ${stats.minificationCache.cacheSize}/${stats.minificationCache.maxCacheSize}
128
+ Memoria: ${formatBytes(stats.minificationCache.memoryUsage)}/${formatBytes(stats.minificationCache.maxMemoryUsage)}
129
+ Compresión Promedio: ${stats.minificationCache.avgCompressionRatio}%
130
+
131
+ 🔄 TRANSFORM OPTIMIZER
132
+ Hit Rate: ${stats.transformOptimizer.hitRate}%
133
+ Cache Hits: ${stats.transformOptimizer.cacheHits}
134
+ Cache Misses: ${stats.transformOptimizer.cacheMisses}
135
+ Transformaciones: ${stats.transformOptimizer.totalTransforms}
136
+ Size: ${stats.transformOptimizer.cacheSize}
137
+ Memoria: ${formatBytes(stats.transformOptimizer.memoryUsage)}
138
+
139
+ 📦 MODULE RESOLUTION
140
+ Hit Rate: ${stats.moduleResolution.cacheHitRate?.toFixed(1)}%
141
+ Cache Hits: ${stats.moduleResolution.cacheHits}
142
+ Cache Misses: ${stats.moduleResolution.cacheMisses}
143
+ Resoluciones: ${stats.moduleResolution.totalResolutions}
144
+ Índice Módulos: ${stats.moduleResolution.moduleIndexSize}
145
+ Índice Alias: ${stats.moduleResolution.aliasIndexSize}
146
+ Tiempo Promedio: ${stats.moduleResolution.averageResolveTime?.toFixed(2)}ms
147
+
148
+ =====================================
149
149
  `;
150
150
  return report;
151
151
  }
@@ -0,0 +1,127 @@
1
+ import { stat } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { parser } from '../parser.js';
4
+ import { ModuleGraph } from './module-graph.js';
5
+ import { PluginDriver } from './plugin-driver.js';
6
+ function guessLoader(filePath) {
7
+ const ext = path.extname(filePath).toLowerCase();
8
+ if (ext === '.vue')
9
+ return 'vue';
10
+ if (ext === '.ts')
11
+ return 'ts';
12
+ if (ext === '.json')
13
+ return 'json';
14
+ if (ext === '.css')
15
+ return 'css';
16
+ return 'js';
17
+ }
18
+ function getAstType(loader) {
19
+ return loader === 'ts' ? 'ts' : 'js';
20
+ }
21
+ function collectModuleRequests(ast) {
22
+ const requests = [];
23
+ const staticImports = ast?.module?.staticImports || [];
24
+ for (const item of staticImports) {
25
+ const value = item?.moduleRequest?.value;
26
+ if (typeof value === 'string')
27
+ requests.push(value);
28
+ }
29
+ const dynamicImports = ast?.module?.dynamicImports || [];
30
+ for (const item of dynamicImports) {
31
+ const value = item?.moduleRequest?.value;
32
+ if (typeof value === 'string')
33
+ requests.push(value);
34
+ }
35
+ return requests;
36
+ }
37
+ async function resolveLocalImport(importer, specifier) {
38
+ if (!specifier.startsWith('.') && !specifier.startsWith('/'))
39
+ return null;
40
+ const base = specifier.startsWith('/')
41
+ ? path.normalize(specifier)
42
+ : path.resolve(path.dirname(importer), specifier);
43
+ const ext = path.extname(base);
44
+ if (ext)
45
+ return base;
46
+ const candidates = [
47
+ `${base}.ts`,
48
+ `${base}.js`,
49
+ `${base}.vue`,
50
+ `${base}.mjs`,
51
+ `${base}.cjs`,
52
+ `${base}.json`,
53
+ path.join(base, 'index.ts'),
54
+ path.join(base, 'index.js'),
55
+ path.join(base, 'index.vue'),
56
+ ];
57
+ for (const candidate of candidates) {
58
+ try {
59
+ await stat(candidate);
60
+ return candidate;
61
+ }
62
+ catch {
63
+ continue;
64
+ }
65
+ }
66
+ return base;
67
+ }
68
+ export class BuildPipeline {
69
+ driver;
70
+ graph;
71
+ constructor(plugins) {
72
+ this.driver = new PluginDriver(plugins);
73
+ this.graph = new ModuleGraph();
74
+ }
75
+ getModuleGraph() {
76
+ return this.graph;
77
+ }
78
+ async hotUpdate(args) {
79
+ return this.driver.hotUpdate(args);
80
+ }
81
+ async compileFile(filePath) {
82
+ const resolved = await this.driver.resolve({
83
+ path: filePath,
84
+ kind: 'entry',
85
+ });
86
+ const entryPath = resolved.path || filePath;
87
+ const loaded = await this.driver.load({ path: entryPath });
88
+ const loadErrors = loaded.errors || [];
89
+ if (!loaded.contents) {
90
+ await this.driver.end(loadErrors);
91
+ return {
92
+ code: '',
93
+ loader: guessLoader(entryPath),
94
+ dependencies: [],
95
+ errors: loadErrors,
96
+ };
97
+ }
98
+ const transformResult = await this.driver.transform({
99
+ path: entryPath,
100
+ contents: loaded.contents,
101
+ loader: loaded.loader || guessLoader(entryPath),
102
+ meta: loaded.meta,
103
+ });
104
+ const transformErrors = transformResult.errors || [];
105
+ const finalCode = transformResult.contents || '';
106
+ const finalLoader = transformResult.loader || loaded.loader || guessLoader(entryPath);
107
+ const ast = await parser(entryPath, finalCode, getAstType(finalLoader));
108
+ const requests = collectModuleRequests(ast);
109
+ const resolvedDeps = [];
110
+ for (const request of requests) {
111
+ const resolvedDep = await resolveLocalImport(entryPath, request);
112
+ if (resolvedDep)
113
+ resolvedDeps.push(resolvedDep);
114
+ }
115
+ this.graph.updateImports(entryPath, resolvedDeps);
116
+ const errors = loadErrors.concat(transformErrors);
117
+ await this.driver.end(errors);
118
+ return {
119
+ code: finalCode,
120
+ loader: finalLoader,
121
+ meta: transformResult.meta || loaded.meta,
122
+ dependencies: resolvedDeps,
123
+ errors,
124
+ };
125
+ }
126
+ }
127
+ //# sourceMappingURL=build-pipeline.js.map