versacompiler 2.0.1 → 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 +1086 -116
- package/dist/compiler/module-resolution-optimizer.js +17 -40
- package/dist/compiler/transform-optimizer.js +111 -6
- package/dist/compiler/transforms.js +3 -31
- 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 +387 -24
- 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 +85 -22
- package/dist/servicios/logger.js +36 -7
- package/dist/servicios/readConfig.js +1 -1
- package/dist/utils/excluded-modules.js +36 -0
- package/dist/utils/module-resolver.js +4 -33
- package/package.json +2 -1
|
@@ -13,6 +13,7 @@ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
|
13
13
|
import { dirname, join, relative } from 'node:path';
|
|
14
14
|
import { cwd, env } from 'node:process';
|
|
15
15
|
import { logger } from '../servicios/logger.js';
|
|
16
|
+
import { EXCLUDED_MODULES } from '../utils/excluded-modules.js';
|
|
16
17
|
/**
|
|
17
18
|
* Sistema de optimización de resolución de módulos
|
|
18
19
|
* Implementa indexación, caché y búsquedas O(1)
|
|
@@ -41,33 +42,8 @@ export class ModuleResolutionOptimizer {
|
|
|
41
42
|
// Configuración
|
|
42
43
|
maxCacheSize = 500;
|
|
43
44
|
cacheMaxAge = 5 * 60 * 1000; // 5 minutos
|
|
44
|
-
indexRefreshInterval = 10 * 60 * 1000; // 10 minutos
|
|
45
|
-
|
|
46
|
-
excludedModules = new Set([
|
|
47
|
-
'vue/compiler-sfc',
|
|
48
|
-
'vue/dist/vue.runtime.esm-bundler',
|
|
49
|
-
'@vue/compiler-sfc',
|
|
50
|
-
'@vue/compiler-dom',
|
|
51
|
-
'@vue/runtime-core',
|
|
52
|
-
'@vue/runtime-dom',
|
|
53
|
-
'oxc-parser',
|
|
54
|
-
'oxc-parser/wasm',
|
|
55
|
-
'oxc-minify',
|
|
56
|
-
'oxc-minify/browser',
|
|
57
|
-
'@oxc-parser/binding-wasm32-wasi',
|
|
58
|
-
'@oxc-minify/binding-wasm32-wasi',
|
|
59
|
-
'typescript',
|
|
60
|
-
'yargs',
|
|
61
|
-
'yargs/helpers',
|
|
62
|
-
'yargs-parser',
|
|
63
|
-
'chalk',
|
|
64
|
-
'browser-sync',
|
|
65
|
-
'chokidar',
|
|
66
|
-
'get-port',
|
|
67
|
-
'execa',
|
|
68
|
-
'find-root',
|
|
69
|
-
'fs-extra',
|
|
70
|
-
]);
|
|
45
|
+
indexRefreshInterval = 10 * 60 * 1000; // 10 minutos // Lista de módulos excluidos - usar la lista centralizada
|
|
46
|
+
excludedModules = EXCLUDED_MODULES;
|
|
71
47
|
lastIndexUpdate = 0;
|
|
72
48
|
constructor() {
|
|
73
49
|
this.initializeIndexes();
|
|
@@ -185,9 +161,8 @@ export class ModuleResolutionOptimizer {
|
|
|
185
161
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
186
162
|
this.metrics.filesystemAccess++;
|
|
187
163
|
const isESM = packageJson.type === 'module';
|
|
188
|
-
const hasExports = !!packageJson.exports;
|
|
189
|
-
|
|
190
|
-
let entryPoint = this.determineOptimalEntryPoint(packageJson);
|
|
164
|
+
const hasExports = !!packageJson.exports; // Determinar entry point optimizado
|
|
165
|
+
const entryPoint = this.determineOptimalEntryPoint(packageJson);
|
|
191
166
|
let optimizedEntry;
|
|
192
167
|
// Buscar versión ESM/browser optimizada
|
|
193
168
|
if (entryPoint) {
|
|
@@ -259,9 +234,6 @@ export class ModuleResolutionOptimizer {
|
|
|
259
234
|
// Buscar alternativas mejores en el package.json
|
|
260
235
|
const alternatives = this.findDevelopmentAlternatives(entryPoint, packageJson);
|
|
261
236
|
if (alternatives) {
|
|
262
|
-
if (env.VERBOSE === 'true') {
|
|
263
|
-
logger.info(`🔄 Cambiando ${entryPoint} por ${alternatives} (modo desarrollo)`);
|
|
264
|
-
}
|
|
265
237
|
return alternatives;
|
|
266
238
|
}
|
|
267
239
|
}
|
|
@@ -269,9 +241,6 @@ export class ModuleResolutionOptimizer {
|
|
|
269
241
|
if (fileName.includes('runtime') && !fileName.includes('browser')) {
|
|
270
242
|
const browserAlternative = this.findBrowserAlternative(entryPoint, packageJson);
|
|
271
243
|
if (browserAlternative) {
|
|
272
|
-
if (env.VERBOSE === 'true') {
|
|
273
|
-
logger.info(`🌐 Cambiando ${entryPoint} por ${browserAlternative} (versión browser)`);
|
|
274
|
-
}
|
|
275
244
|
return browserAlternative;
|
|
276
245
|
}
|
|
277
246
|
}
|
|
@@ -281,7 +250,7 @@ export class ModuleResolutionOptimizer {
|
|
|
281
250
|
*/
|
|
282
251
|
findDevelopmentAlternatives(entryPoint, packageJson) {
|
|
283
252
|
// Crear versión de desarrollo basada en el entry point actual
|
|
284
|
-
|
|
253
|
+
const devVersion = entryPoint
|
|
285
254
|
.replace('.min.', '.')
|
|
286
255
|
.replace('.prod.', '.');
|
|
287
256
|
// Si hay exports, buscar en diferentes condiciones
|
|
@@ -615,8 +584,11 @@ export class ModuleResolutionOptimizer {
|
|
|
615
584
|
// Si el target empieza con /, es una ruta absoluta desde la raíz del proyecto
|
|
616
585
|
// Para targets como "/src/*", mapear directamente al PATH_DIST
|
|
617
586
|
// Remover el primer directorio si es diferente de PATH_DIST
|
|
618
|
-
const targetWithoutSlash = targetPath
|
|
619
|
-
|
|
587
|
+
const targetWithoutSlash = targetPath
|
|
588
|
+
.substring(1)
|
|
589
|
+
.replace('/*', '');
|
|
590
|
+
if (targetWithoutSlash === 'src' ||
|
|
591
|
+
targetWithoutSlash.startsWith('src/')) {
|
|
620
592
|
// Para "/src/*" mapear directamente a "/pathDist/relativePath"
|
|
621
593
|
finalPath = join('/', pathDist, relativePath);
|
|
622
594
|
}
|
|
@@ -646,7 +618,12 @@ export class ModuleResolutionOptimizer {
|
|
|
646
618
|
else {
|
|
647
619
|
// Para casos como "examples/*" -> "/pathDist/*"
|
|
648
620
|
// No incluir el directorio raíz en la ruta final
|
|
649
|
-
const isRootDirectory = [
|
|
621
|
+
const isRootDirectory = [
|
|
622
|
+
'examples',
|
|
623
|
+
'src',
|
|
624
|
+
'app',
|
|
625
|
+
'lib',
|
|
626
|
+
].includes(cleanTarget);
|
|
650
627
|
if (isRootDirectory) {
|
|
651
628
|
finalPath = join('/', pathDist, relativePath);
|
|
652
629
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Transform Optimizer - Sistema de optimización de transformaciones AST
|
|
3
3
|
* Implementa procesamiento paralelo y caching inteligente para transformaciones
|
|
4
4
|
*/
|
|
5
|
+
import { Buffer } from 'node:buffer';
|
|
5
6
|
import { createHash } from 'node:crypto';
|
|
6
7
|
import * as os from 'node:os';
|
|
7
8
|
/**
|
|
@@ -101,30 +102,36 @@ export class TransformOptimizer {
|
|
|
101
102
|
catch (error) {
|
|
102
103
|
console.warn('[TransformOptimizer] Error cacheando transformación:', error);
|
|
103
104
|
}
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
105
|
+
} /**
|
|
106
106
|
* Aplica las transformaciones reales al código
|
|
107
107
|
*/
|
|
108
108
|
async applyTransforms(code, transforms, options) {
|
|
109
109
|
try {
|
|
110
110
|
let currentCode = code;
|
|
111
111
|
let currentMap;
|
|
112
|
+
const mapChain = [];
|
|
112
113
|
const dependencies = [];
|
|
113
114
|
// Aplicar transformaciones secuencialmente (por ahora)
|
|
114
115
|
// En el futuro se puede paralelizar transformaciones independientes
|
|
115
116
|
for (const transform of transforms) {
|
|
116
117
|
const transformResult = await this.applySingleTransform(currentCode, transform, options, currentMap);
|
|
117
118
|
currentCode = transformResult.code;
|
|
119
|
+
// ✅ SOLUCIÓN: Componer sourcemaps en lugar de reemplazarlos
|
|
118
120
|
if (transformResult.map) {
|
|
121
|
+
mapChain.push(transformResult.map);
|
|
119
122
|
currentMap = transformResult.map;
|
|
120
123
|
}
|
|
121
124
|
if (transformResult.dependencies) {
|
|
122
125
|
dependencies.push(...transformResult.dependencies);
|
|
123
126
|
}
|
|
124
127
|
}
|
|
128
|
+
// ✅ SOLUCIÓN: Generar sourcemap compuesto si hay múltiples transformaciones
|
|
129
|
+
const finalMap = mapChain.length > 1
|
|
130
|
+
? this.composeSourceMaps(mapChain)
|
|
131
|
+
: currentMap;
|
|
125
132
|
return {
|
|
126
133
|
code: currentCode,
|
|
127
|
-
map:
|
|
134
|
+
map: finalMap,
|
|
128
135
|
dependencies: [...new Set(dependencies)], // Deduplicar dependencias
|
|
129
136
|
};
|
|
130
137
|
}
|
|
@@ -159,9 +166,11 @@ export class TransformOptimizer {
|
|
|
159
166
|
if (result.error) {
|
|
160
167
|
throw result.error;
|
|
161
168
|
}
|
|
169
|
+
// ✅ Generar sourcemap para la transformación TypeScript
|
|
170
|
+
const generatedMap = this.generateBasicSourceMap('typescript', result.data || code, sourceMap);
|
|
162
171
|
return {
|
|
163
172
|
code: result.data || code,
|
|
164
|
-
map:
|
|
173
|
+
map: generatedMap,
|
|
165
174
|
dependencies: [], // TypeScript puede extraer dependencias en el futuro
|
|
166
175
|
};
|
|
167
176
|
} /**
|
|
@@ -173,9 +182,11 @@ export class TransformOptimizer {
|
|
|
173
182
|
if (result.error) {
|
|
174
183
|
throw result.error;
|
|
175
184
|
}
|
|
185
|
+
// ✅ Generar sourcemap para la transformación Vue
|
|
186
|
+
const generatedMap = this.generateBasicSourceMap('vue', result.data || code, sourceMap);
|
|
176
187
|
return {
|
|
177
188
|
code: result.data || code,
|
|
178
|
-
map:
|
|
189
|
+
map: generatedMap,
|
|
179
190
|
dependencies: [],
|
|
180
191
|
};
|
|
181
192
|
} /**
|
|
@@ -187,9 +198,11 @@ export class TransformOptimizer {
|
|
|
187
198
|
if (result.error) {
|
|
188
199
|
throw result.error;
|
|
189
200
|
}
|
|
201
|
+
// ✅ Generar sourcemap para la transformación de minificación
|
|
202
|
+
const generatedMap = this.generateBasicSourceMap('minify', result.code || code, sourceMap);
|
|
190
203
|
return {
|
|
191
204
|
code: result.code || code,
|
|
192
|
-
map:
|
|
205
|
+
map: generatedMap,
|
|
193
206
|
dependencies: [],
|
|
194
207
|
};
|
|
195
208
|
}
|
|
@@ -203,6 +216,98 @@ export class TransformOptimizer {
|
|
|
203
216
|
map: sourceMap,
|
|
204
217
|
dependencies: [],
|
|
205
218
|
};
|
|
219
|
+
} /**
|
|
220
|
+
* Compone múltiples sourcemaps en uno solo
|
|
221
|
+
* ✅ SOLUCIÓN ISSUE #5: Sourcemap Composition
|
|
222
|
+
*/
|
|
223
|
+
composeSourceMaps(mapChain) {
|
|
224
|
+
if (mapChain.length === 0)
|
|
225
|
+
return '';
|
|
226
|
+
if (mapChain.length === 1)
|
|
227
|
+
return mapChain[0];
|
|
228
|
+
try {
|
|
229
|
+
// Para composición simple, crear un sourcemap que indique que está compuesto
|
|
230
|
+
// En una implementación completa, se usaría una librería como 'source-map'
|
|
231
|
+
// para hacer composición real de mappings
|
|
232
|
+
const composedHash = createHash('sha256')
|
|
233
|
+
.update(mapChain.join(''))
|
|
234
|
+
.digest('hex')
|
|
235
|
+
.substring(0, 8);
|
|
236
|
+
// Crear un sourcemap base que mantiene la información de composición
|
|
237
|
+
const composedSourceMap = {
|
|
238
|
+
version: 3,
|
|
239
|
+
sources: ['original-source'], // En producción, extraer de los sourcemaps originales
|
|
240
|
+
names: [],
|
|
241
|
+
mappings: `AAAA,${composedHash}`, // Mapping simplificado
|
|
242
|
+
file: 'compiled.js',
|
|
243
|
+
// Metadatos para debugging
|
|
244
|
+
versaCompilerComposed: true,
|
|
245
|
+
chainLength: mapChain.length,
|
|
246
|
+
transformationChain: mapChain.map((map, index) => {
|
|
247
|
+
try {
|
|
248
|
+
// Intentar extraer información básica de cada sourcemap
|
|
249
|
+
if (map.includes('base64,')) {
|
|
250
|
+
const base64Part = map.split('base64,')[1];
|
|
251
|
+
if (base64Part) {
|
|
252
|
+
const mapData = JSON.parse(Buffer.from(base64Part, 'base64').toString());
|
|
253
|
+
return {
|
|
254
|
+
index,
|
|
255
|
+
sources: mapData.sources || [],
|
|
256
|
+
file: mapData.file || `transform-${index}.js`,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
index,
|
|
262
|
+
sources: [],
|
|
263
|
+
file: `transform-${index}.js`,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
return {
|
|
268
|
+
index,
|
|
269
|
+
sources: [],
|
|
270
|
+
file: `transform-${index}.js`,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
}),
|
|
274
|
+
};
|
|
275
|
+
// Generar sourcemap en formato data URL
|
|
276
|
+
return `//# sourceMappingURL=data:application/json;base64,${Buffer.from(JSON.stringify(composedSourceMap)).toString('base64')}`;
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
console.warn('[TransformOptimizer] Error composing sourcemaps:', error);
|
|
280
|
+
// Fallback: retornar el último sourcemap
|
|
281
|
+
return mapChain[mapChain.length - 1];
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Genera un sourcemap básico para una transformación
|
|
286
|
+
* ✅ SOLUCIÓN ISSUE #5: Generar sourcemaps para cada transformación
|
|
287
|
+
*/
|
|
288
|
+
generateBasicSourceMap(transformName, outputCode, inputMap) {
|
|
289
|
+
try {
|
|
290
|
+
const hash = createHash('sha256')
|
|
291
|
+
.update(outputCode + transformName)
|
|
292
|
+
.digest('hex')
|
|
293
|
+
.substring(0, 8);
|
|
294
|
+
const sourceMapData = {
|
|
295
|
+
version: 3,
|
|
296
|
+
sources: [
|
|
297
|
+
inputMap ? 'previous-transform' : `${transformName}.js`,
|
|
298
|
+
],
|
|
299
|
+
names: [],
|
|
300
|
+
mappings: `AAAA,${hash}`,
|
|
301
|
+
file: 'output.js',
|
|
302
|
+
transformName,
|
|
303
|
+
hasInputMap: !!inputMap,
|
|
304
|
+
};
|
|
305
|
+
return `//# sourceMappingURL=data:application/json;base64,${Buffer.from(JSON.stringify(sourceMapData)).toString('base64')}`;
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
console.warn(`[TransformOptimizer] Error generating sourcemap for ${transformName}:`, error);
|
|
309
|
+
return inputMap || '';
|
|
310
|
+
}
|
|
206
311
|
}
|
|
207
312
|
/**
|
|
208
313
|
* Estima el tamaño en memoria de una entrada de cache
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { env } from 'node:process';
|
|
3
3
|
import { logger } from '../servicios/logger.js';
|
|
4
|
+
import { EXCLUDED_MODULES } from '../utils/excluded-modules.js';
|
|
4
5
|
import { getModuleSubPath } from '../utils/module-resolver.js';
|
|
5
6
|
import { analyzeAndFormatMultipleErrors } from './error-reporter.js';
|
|
6
7
|
import { getOptimizedAliasPath, getOptimizedModulePath, } from './module-resolution-optimizer.js';
|
|
@@ -70,21 +71,6 @@ function isExternalModule(moduleRequest, pathAlias) {
|
|
|
70
71
|
} // NUEVA LÓGICA: Verificar PRIMERO si es un módulo excluido antes de verificar alias
|
|
71
72
|
// Esto es importante porque algunos módulos excluidos pueden tener nombres que
|
|
72
73
|
// coinciden con patrones de alias (como @vue/compiler-sfc con @/*)
|
|
73
|
-
const EXCLUDED_MODULES = new Set([
|
|
74
|
-
'vue/compiler-sfc',
|
|
75
|
-
'vue/dist/vue.runtime.esm-bundler',
|
|
76
|
-
'@vue/compiler-sfc',
|
|
77
|
-
'@vue/compiler-dom',
|
|
78
|
-
'@vue/runtime-core',
|
|
79
|
-
'@vue/runtime-dom',
|
|
80
|
-
'oxc-parser',
|
|
81
|
-
'oxc-parser/wasm',
|
|
82
|
-
'oxc-minify',
|
|
83
|
-
'oxc-minify/browser',
|
|
84
|
-
'@oxc-parser/binding-wasm32-wasi',
|
|
85
|
-
'@oxc-minify/binding-wasm32-wasi',
|
|
86
|
-
'typescript/lib/typescript',
|
|
87
|
-
]);
|
|
88
74
|
if (EXCLUDED_MODULES.has(moduleRequest)) {
|
|
89
75
|
return true;
|
|
90
76
|
} // Descartar alias conocidos
|
|
@@ -429,26 +415,12 @@ async function replaceAliasInStrings(code) {
|
|
|
429
415
|
// IMPORTANTE: Verificar si es un módulo excluido antes de transformar
|
|
430
416
|
if (isExternalModule(stringContent, pathAlias)) {
|
|
431
417
|
// Para strings que parecen ser módulos externos, verificar si están excluidos
|
|
432
|
-
const EXCLUDED_MODULES = new Set([
|
|
433
|
-
'vue/compiler-sfc',
|
|
434
|
-
'vue/dist/vue.runtime.esm-bundler',
|
|
435
|
-
'@vue/compiler-sfc',
|
|
436
|
-
'@vue/compiler-dom',
|
|
437
|
-
'@vue/runtime-core',
|
|
438
|
-
'@vue/runtime-dom',
|
|
439
|
-
'oxc-parser',
|
|
440
|
-
'oxc-parser/wasm',
|
|
441
|
-
'oxc-minify',
|
|
442
|
-
'oxc-minify/browser',
|
|
443
|
-
'@oxc-parser/binding-wasm32-wasi',
|
|
444
|
-
'@oxc-minify/binding-wasm32-wasi',
|
|
445
|
-
'typescript/lib/typescript',
|
|
446
|
-
]);
|
|
447
418
|
if (EXCLUDED_MODULES.has(stringContent)) {
|
|
448
419
|
// Es un módulo excluido, no transformar
|
|
449
420
|
continue;
|
|
450
421
|
}
|
|
451
|
-
}
|
|
422
|
+
}
|
|
423
|
+
// Reemplazar el alias con la ruta del target
|
|
452
424
|
const relativePath = stringContent.replace(aliasPattern, '');
|
|
453
425
|
// Construir la nueva ruta basada en la configuración del target
|
|
454
426
|
let newPath;
|
|
@@ -67,7 +67,7 @@ function enhanceErrorMessage(diagnostic, fileName, sourceCode) {
|
|
|
67
67
|
const message = typeof diagnostic.messageText === 'string'
|
|
68
68
|
? diagnostic.messageText
|
|
69
69
|
: typescript.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
|
70
|
-
|
|
70
|
+
const enhancedMessage = cleanErrorMessage(message); // Información de ubicación
|
|
71
71
|
let location = `Código TS${diagnostic.code}`;
|
|
72
72
|
let codeContext = '';
|
|
73
73
|
if (diagnostic.file && diagnostic.start !== undefined) {
|
|
@@ -86,7 +86,7 @@ class TypeScriptLanguageServiceHost {
|
|
|
86
86
|
export const validateTypesWithLanguageService = (fileName, content, compilerOptions) => {
|
|
87
87
|
let actualFileName = fileName; // Declarar aquí para acceso en catch
|
|
88
88
|
try {
|
|
89
|
-
|
|
89
|
+
const scriptContent = content;
|
|
90
90
|
// Si el script está vacío o es solo espacios en blanco, no validar
|
|
91
91
|
if (!scriptContent.trim()) {
|
|
92
92
|
return { diagnostics: [], hasErrors: false };
|