versacompiler 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -161,9 +161,8 @@ export class ModuleResolutionOptimizer {
161
161
  const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
162
162
  this.metrics.filesystemAccess++;
163
163
  const isESM = packageJson.type === 'module';
164
- const hasExports = !!packageJson.exports;
165
- // Determinar entry point optimizado
166
- let entryPoint = this.determineOptimalEntryPoint(packageJson);
164
+ const hasExports = !!packageJson.exports; // Determinar entry point optimizado
165
+ const entryPoint = this.determineOptimalEntryPoint(packageJson);
167
166
  let optimizedEntry;
168
167
  // Buscar versión ESM/browser optimizada
169
168
  if (entryPoint) {
@@ -251,7 +250,7 @@ export class ModuleResolutionOptimizer {
251
250
  */
252
251
  findDevelopmentAlternatives(entryPoint, packageJson) {
253
252
  // Crear versión de desarrollo basada en el entry point actual
254
- let devVersion = entryPoint
253
+ const devVersion = entryPoint
255
254
  .replace('.min.', '.')
256
255
  .replace('.prod.', '.');
257
256
  // Si hay exports, buscar en diferentes condiciones
@@ -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
- let enhancedMessage = cleanErrorMessage(message); // Información de ubicación
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
- let scriptContent = content;
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 };
@@ -18,10 +18,10 @@ export class TypeScriptWorkerPool {
18
18
  workerPath;
19
19
  initPromise = null;
20
20
  isInitialized = false; // Configuración optimizada con reciclaje de workers
21
- TASK_TIMEOUT = 10000; // 10 segundos por tarea
21
+ TASK_TIMEOUT = 15000; // 15 segundos por tarea (aumentado)
22
22
  WORKER_INIT_TIMEOUT = 5000; // 5 segundos para inicializar
23
- MAX_TASKS_PER_WORKER = 50; // Máximo de tareas por worker antes de reciclaje
24
- WORKER_MEMORY_CHECK_INTERVAL = 100; // Verificar cada 100 tareas
23
+ MAX_TASKS_PER_WORKER = 25; // Reducido para liberar memoria más frecuentemente
24
+ WORKER_MEMORY_CHECK_INTERVAL = 50; // Verificar cada 50 tareas (más frecuente)
25
25
  // Métricas de rendimiento
26
26
  totalTasks = 0;
27
27
  completedTasks = 0;
@@ -31,22 +31,21 @@ export class TypeScriptWorkerPool {
31
31
  const cpuCount = os.cpus().length;
32
32
  this.poolSize = Math.min(Math.max(cpuCount - 1, 2), 8); // Entre 2 y 8 workers
33
33
  this.workerPath = path.join(process.env.PATH_PROY || path.join(process.cwd(), 'src'), 'compiler', 'typescript-worker-thread.cjs');
34
- // ✨ ISSUE #4: Configurar monitoreo de memoria automático
35
- this.startMemoryMonitoring();
34
+ // ✨ ISSUE #4: Configurar monitoreo de memoria automático this.startMemoryMonitoring();
36
35
  }
37
36
  // ✨ ISSUE #4: Métodos de control de memoria y timeouts
38
37
  /**
39
38
  * Inicia el monitoreo automático de memoria de workers
40
39
  */
41
40
  startMemoryMonitoring() {
42
- // Monitoreo cada 30 segundos
41
+ // Monitoreo cada 15 segundos (más frecuente)
43
42
  setInterval(() => {
44
43
  this.checkWorkersMemory();
45
- }, 30000);
46
- // Limpieza de workers inactivos cada 5 minutos
44
+ }, 15000);
45
+ // Limpieza de workers inactivos cada 2 minutos (más frecuente)
47
46
  setInterval(() => {
48
47
  this.cleanupInactiveWorkers();
49
- }, 300000);
48
+ }, 120000);
50
49
  }
51
50
  /**
52
51
  * Verifica el uso de memoria de todos los workers con medición real
@@ -128,13 +127,12 @@ export class TypeScriptWorkerPool {
128
127
  reasons.push(`tareas procesadas exceden ${TASK_LIMIT} (actual: ${poolWorker.tasksProcessed})`);
129
128
  }
130
129
  return reasons.join(', ');
131
- }
132
- /**
130
+ } /**
133
131
  * Limpia workers que han estado inactivos por mucho tiempo
134
132
  */
135
133
  async cleanupInactiveWorkers() {
136
134
  const now = Date.now();
137
- const INACTIVE_TIMEOUT = 10 * 60 * 1000; // 10 minutos
135
+ const INACTIVE_TIMEOUT = 5 * 60 * 1000; // 5 minutos (reducido)
138
136
  for (const poolWorker of this.workers) {
139
137
  const timeSinceLastActivity = now - poolWorker.lastActivityTime;
140
138
  if (timeSinceLastActivity > INACTIVE_TIMEOUT &&
@@ -144,14 +142,13 @@ export class TypeScriptWorkerPool {
144
142
  await this.recycleWorker(poolWorker);
145
143
  }
146
144
  }
147
- }
148
- /**
145
+ } /**
149
146
  * Verifica si un worker debe ser reciclado por límites de memoria/tiempo
150
147
  */
151
148
  shouldRecycleWorker(poolWorker) {
152
149
  const now = Date.now();
153
- const MEMORY_LIMIT = 50 * 1024 * 1024; // 50MB
154
- const TIME_LIMIT = 30 * 60 * 1000; // 30 minutos
150
+ const MEMORY_LIMIT = 30 * 1024 * 1024; // 30MB (reducido)
151
+ const TIME_LIMIT = 15 * 60 * 1000; // 15 minutos (reducido)
155
152
  const TASK_LIMIT = this.MAX_TASKS_PER_WORKER;
156
153
  return (poolWorker.memoryUsage > MEMORY_LIMIT ||
157
154
  now - poolWorker.creationTime > TIME_LIMIT ||
@@ -158,9 +158,8 @@ class WorkerTypeScriptLanguageServiceHost {
158
158
  */
159
159
  function validateTypesInWorker(fileName, content, compilerOptions) {
160
160
  let actualFileName = fileName;
161
-
162
161
  try {
163
- let scriptContent = content;
162
+ const scriptContent = content;
164
163
 
165
164
  // Si el script está vacío o es solo espacios en blanco, no validar
166
165
  if (!scriptContent.trim()) {
@@ -56,7 +56,7 @@ function getVueInstanceFromElement(selector = '#app') {
56
56
  function findVueInstanceInDOM() {
57
57
  const allElements = document.querySelectorAll('*');
58
58
 
59
- for (let element of allElements) {
59
+ for (const element of allElements) {
60
60
  // Vue 3
61
61
  if (element.__vue_app__) {
62
62
  return element.__vue_app__;
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { hideErrorOverlay, showErrorOverlay } from './errorScreen.js';
13
- import obtenerInstanciaVue from './getInstanciaVue.js';
13
+ import { obtenerInstanciaVue } from './getInstanciaVue.js';
14
14
  import { reloadComponent } from './VueHRM.js';
15
15
 
16
16
  /**
package/dist/main.js CHANGED
@@ -132,9 +132,18 @@ async function main() {
132
132
  })
133
133
  .parse());
134
134
  try {
135
- logger.log(`\n\n` +
136
- chalk.blue('VersaCompiler') +
137
- ' - Servidor de Desarrollo HRM y compilador de archivos Vue/ts/js\n\n');
135
+ // 🎨 Header moderno y elegante
136
+ const headerLine = '━'.repeat(60);
137
+ logger.log(`\n` +
138
+ chalk.cyan(headerLine) +
139
+ `\n` +
140
+ chalk.bold.cyan(' ⚡ VersaCompiler ') +
141
+ chalk.gray('v2.0.3') +
142
+ `\n` +
143
+ chalk.gray(' Vue · TypeScript · JavaScript Compiler') +
144
+ `\n` +
145
+ chalk.cyan(headerLine) +
146
+ `\n`);
138
147
  if (argv.init) {
139
148
  logger.info('Iniciando la configuración...');
140
149
  const { initConfig } = await loadConfigModule();
@@ -149,20 +158,58 @@ async function main() {
149
158
  env.TAILWIND =
150
159
  argv.tailwind === undefined ? 'true' : String(argv.tailwind);
151
160
  env.ENABLE_LINTER = String(argv.linter);
152
- env.VERBOSE = argv.verbose ? 'true' : 'false';
153
- logger.info(chalk.green('Configuración de VersaCompiler:'));
154
- logger.info(chalk.green(`Watch: ${argv.watch}`));
155
- logger.info(chalk.green(`All: ${env.isALL}`));
156
- logger.info(chalk.green(`File: ${argv.file || 'N/A'}`));
157
- logger.info(chalk.green(`Prod: ${env.isPROD}`));
158
- logger.info(chalk.green(`Tailwind: ${env.TAILWIND}`));
159
- logger.info(chalk.green(`Minification: ${env.isPROD}`));
160
- logger.info(chalk.green(`Linter: ${env.ENABLE_LINTER}`));
161
- logger.info(chalk.green(`Verbose: ${env.VERBOSE}`));
162
- logger.info(chalk.green(`Clean Output: ${argv.cleanOutput}`));
163
- logger.info(chalk.green(`Clean Cache: ${argv.cleanCache}`));
164
- logger.info(chalk.green(`Type Check: ${argv.typeCheck}`));
165
- logger.log(`\n`);
161
+ env.VERBOSE = argv.verbose ? 'true' : 'false'; // 🎯 Configuración moderna y organizada
162
+ logger.info(chalk.bold.blue('⚙️ Configuración'));
163
+ logger.info(chalk.gray(' ┌─ Modo de ejecución'));
164
+ const modes = [
165
+ { label: 'Observar', value: argv.watch, icon: '👀' },
166
+ {
167
+ label: 'Todos los archivos',
168
+ value: env.isALL === 'true',
169
+ icon: '📁',
170
+ },
171
+ { label: 'Archivo único', value: !!argv.file, icon: '📄' },
172
+ { label: 'Producción', value: env.isPROD === 'true', icon: '🏭' },
173
+ ];
174
+ const features = [
175
+ { label: 'Tailwind', value: env.TAILWIND === 'true', icon: '🎨' },
176
+ { label: 'Minificación', value: env.isPROD === 'true', icon: '🗜️' },
177
+ {
178
+ label: 'Linter',
179
+ value: env.ENABLE_LINTER === 'true',
180
+ icon: '🔍',
181
+ },
182
+ { label: 'Verificar tipos', value: argv.typeCheck, icon: '📘' },
183
+ { label: 'Detallado', value: env.VERBOSE === 'true', icon: '📝' },
184
+ ];
185
+ modes.forEach(mode => {
186
+ const status = mode.value ? chalk.green('●') : chalk.gray('○');
187
+ const label = mode.value
188
+ ? chalk.green(mode.label)
189
+ : chalk.gray(mode.label);
190
+ logger.info(chalk.gray(' │ ') + status + ` ${mode.icon} ${label}`);
191
+ });
192
+ logger.info(chalk.gray(' ├─ Características'));
193
+ features.forEach(feature => {
194
+ const status = feature.value ? chalk.green('●') : chalk.gray('○');
195
+ const label = feature.value
196
+ ? chalk.green(feature.label)
197
+ : chalk.gray(feature.label);
198
+ logger.info(chalk.gray(' │ ') + status + ` ${feature.icon} ${label}`);
199
+ });
200
+ if (argv.file) {
201
+ logger.info(chalk.gray(' ├─ Objetivo'));
202
+ logger.info(chalk.gray(' │ ') + chalk.blue('📄 ') + argv.file);
203
+ }
204
+ if (argv.cleanOutput) {
205
+ logger.info(chalk.gray(' ├─ Limpieza'));
206
+ logger.info(chalk.gray(' │ ') + chalk.yellow('🧹 Limpiar salida'));
207
+ }
208
+ if (argv.cleanCache) {
209
+ logger.info(chalk.gray(' │ ') + chalk.yellow('🗑️ Limpiar caché'));
210
+ }
211
+ logger.info(chalk.gray(' └─ ¡Listo para compilar!'));
212
+ logger.log('');
166
213
  env.typeCheck = argv.typeCheck ? 'true' : 'false';
167
214
  env.cleanCache = argv.cleanCache ? 'true' : 'false';
168
215
  env.yes = argv.y ? 'true' : 'false';
@@ -279,7 +279,7 @@ const loadChalk = async () => {
279
279
  export async function browserSyncServer() {
280
280
  try {
281
281
  let bs = null;
282
- const AssetsOmit = env.AssetsOmit === 'true' ? true : false;
282
+ const AssetsOmit = env.AssetsOmit === 'true';
283
283
  let proxy = {
284
284
  server: './',
285
285
  };
@@ -209,13 +209,19 @@ export async function cleanOutputDir(outputDir, primerInteraccion = true) {
209
209
  '? (s / N) : ');
210
210
  if (answer.toLowerCase() !== 's') {
211
211
  logger.info('🛑 Compilación cancelada por el usuario.');
212
- process.exit(0);
212
+ if (process.env.NODE_ENV !== 'test') {
213
+ process.exit(0);
214
+ }
215
+ return;
213
216
  }
214
217
  }
215
218
  }
216
219
  catch (error) {
217
220
  logger.error(`Error en la entrada del usuario: ${error}`);
218
- process.exit(1);
221
+ if (process.env.NODE_ENV !== 'test') {
222
+ process.exit(1);
223
+ }
224
+ throw error;
219
225
  }
220
226
  }
221
227
  const chalkInstance = await loadChalk();
@@ -271,7 +277,10 @@ export async function initChokidar(bs) {
271
277
  try {
272
278
  if (!env.PATH_SOURCE) {
273
279
  logger.error('Error: La variable de entorno PATH_SOURCE no está definida.');
274
- process.exit(1);
280
+ if (process.env.NODE_ENV !== 'test') {
281
+ process.exit(1);
282
+ }
283
+ throw new Error('PATH_SOURCE no está definida');
275
284
  }
276
285
  const watchJS = `${env.PATH_SOURCE}/**/*.js`;
277
286
  const watchVue = `${env.PATH_SOURCE}/**/*.vue`;
@@ -361,7 +370,10 @@ export async function initChokidar(bs) {
361
370
  }
362
371
  catch (error) {
363
372
  logger.error(`🚩 :Error al iniciar watch: ${error instanceof Error ? error.message : String(error)}`);
364
- process.exit(1);
373
+ if (process.env.NODE_ENV !== 'test') {
374
+ process.exit(1);
375
+ }
376
+ throw error;
365
377
  }
366
378
  }
367
379
  //# sourceMappingURL=file-watcher.js.map
@@ -1,33 +1,62 @@
1
1
  import * as process from 'node:process';
2
+ // Función para obtener ProgressManager (lazy import para evitar dependencias circulares)
3
+ let getProgressManager = null;
4
+ export function setProgressManagerGetter(getter) {
5
+ getProgressManager = getter;
6
+ }
2
7
  class Logger {
3
8
  constructor() {
4
9
  // Bind console methods
5
10
  process.stdout.write = process.stdout.write.bind(process.stdout);
6
11
  process.stderr.write = process.stderr.write.bind(process.stderr);
7
12
  }
13
+ writeMessage(message, useStderr = false, immediate = false) {
14
+ if (getProgressManager) {
15
+ const progressManager = getProgressManager();
16
+ if (progressManager && progressManager.isActive()) {
17
+ // Si el progreso está activo, usar el sistema de logs apropiado
18
+ if (immediate) {
19
+ progressManager.addImmediateLog(message);
20
+ }
21
+ else {
22
+ progressManager.addLog(message);
23
+ }
24
+ return;
25
+ }
26
+ }
27
+ // Comportamiento normal si no hay progreso activo
28
+ if (useStderr) {
29
+ process.stderr.write(message + '\n');
30
+ }
31
+ else {
32
+ process.stdout.write(message + '\n');
33
+ }
34
+ }
8
35
  log(...args) {
9
- process.stdout.write(args.map(arg => String(arg)).join(' ') + '\n');
36
+ this.writeMessage(args.map(arg => String(arg)).join(' '));
10
37
  }
11
38
  info(...args) {
12
- process.stdout.write(args.map(arg => String(arg)).join(' ') + '\n');
39
+ // En modo verbose, mostrar logs inmediatamente
40
+ const isVerbose = process.env.VERBOSE === 'true';
41
+ this.writeMessage(args.map(arg => String(arg)).join(' '), false, isVerbose);
13
42
  }
14
43
  error(...args) {
15
- process.stderr.write(args.map(arg => String(arg)).join(' ') + '\n');
44
+ this.writeMessage(args.map(arg => String(arg)).join(' '), true);
16
45
  }
17
46
  warn(...args) {
18
- process.stderr.write(args.map(arg => String(arg)).join(' ') + '\n');
47
+ this.writeMessage(args.map(arg => String(arg)).join(' '), true);
19
48
  }
20
49
  debug(...args) {
21
- process.stdout.write(args.map(arg => String(arg)).join(' ') + '\n');
50
+ this.writeMessage(args.map(arg => String(arg)).join(' '));
22
51
  }
23
52
  fatal(...args) {
24
- process.stderr.write(args.map(arg => String(arg)).join(' ') + '\n');
53
+ this.writeMessage(args.map(arg => String(arg)).join(' '), true);
25
54
  }
26
55
  table(data, title) {
27
56
  const tableString = title
28
57
  ? console.table(data, title)
29
58
  : console.table(data);
30
- process.stdout.write(String(tableString) + '\n');
59
+ this.writeMessage(String(tableString));
31
60
  }
32
61
  }
33
62
  export const logger = new Logger();
@@ -341,7 +341,7 @@ export async function readConfig() {
341
341
  if (!tsConfig.compilerOptions.sourceRoot) {
342
342
  env.tsConfig = safeJsonStringify(tsConfig, '{}');
343
343
  }
344
- logger.info('Configuración cargada y validada exitosamente');
344
+ logger.info(' Configuration loaded and validated successfully');
345
345
  return true;
346
346
  }
347
347
  catch (error) {
@@ -228,7 +228,6 @@ function simpleESMResolver(moduleName) {
228
228
  try {
229
229
  const nodeModulesPath = join(cwd(), 'node_modules', moduleName);
230
230
  let packagePath;
231
- let packageJson;
232
231
  try {
233
232
  packagePath = join(nodeModulesPath, 'package.json');
234
233
  if (!fs.existsSync(packagePath)) {
@@ -238,7 +237,7 @@ function simpleESMResolver(moduleName) {
238
237
  catch {
239
238
  return null;
240
239
  }
241
- packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
240
+ const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
242
241
  const moduleDir = dirname(packagePath);
243
242
  const isESM = packageJson.type === 'module'; // Determinar el entry point ESM/Browser optimizado
244
243
  let entryPoint = null;
@@ -381,7 +380,7 @@ function getNodeModulesRelativePath(fullPath, _fromFile) {
381
380
  const idx = fullPath.indexOf('node_modules');
382
381
  if (idx !== -1) {
383
382
  // Extraer solo la parte desde node_modules en adelante
384
- let relativePath = fullPath.substring(idx).replace(/\\/g, '/');
383
+ const relativePath = fullPath.substring(idx).replace(/\\/g, '/');
385
384
  // Devolver ruta absoluta desde la raíz del proyecto (sin ../)
386
385
  // Esto permite que los archivos compilados accedan directamente a node_modules
387
386
  return '/' + relativePath;
@@ -428,7 +427,7 @@ export function getModuleSubPath(moduleName, fromFile) {
428
427
  if (packageJson.exports &&
429
428
  typeof packageJson.exports === 'object') {
430
429
  const exportKey = `./${subPath}`;
431
- let exportPath = packageJson.exports[exportKey];
430
+ const exportPath = packageJson.exports[exportKey];
432
431
  if (exportPath) {
433
432
  if (typeof exportPath === 'string') {
434
433
  return getNodeModulesRelativePath(join(moduleDir, exportPath), fromFile);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "versacompiler",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "Una herramienta para compilar y minificar archivos .vue, .js y .ts para proyectos de Vue 3 con soporte para TypeScript.",
5
5
  "main": "dist/main.js",
6
6
  "bin": {