versacompiler 2.0.0 → 2.0.2

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.
@@ -0,0 +1,367 @@
1
+ import { readdir, rm, stat, unlink } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import process, { env } from 'node:process';
4
+ import * as chokidar from 'chokidar';
5
+ import { minimatch } from 'minimatch';
6
+ import { getOutputPath, initCompile, normalizeRuta } from '../compiler/compile.js';
7
+ import { promptUser } from '../utils/promptUser.js';
8
+ import { emitirCambios } from './browserSync.js';
9
+ import { logger } from './logger.js';
10
+ // Lazy loading para chalk
11
+ let chalk;
12
+ async function loadChalk() {
13
+ if (!chalk) {
14
+ chalk = (await import('chalk')).default;
15
+ }
16
+ return chalk;
17
+ }
18
+ class WatchDebouncer {
19
+ pendingChanges = new Map();
20
+ debounceTimer = null;
21
+ DEBOUNCE_DELAY = 300; // 300ms debounce
22
+ BATCH_SIZE = 10; // Máximo archivos por batch
23
+ isProcessing = false;
24
+ browserSyncInstance = null; // ✨ Almacenar referencia a browserSync
25
+ /**
26
+ * Establece la instancia de browserSync
27
+ */
28
+ setBrowserSyncInstance(bs) {
29
+ this.browserSyncInstance = bs;
30
+ }
31
+ /**
32
+ * Añade un cambio al sistema de debouncing
33
+ */
34
+ addChange(filePath, action, extensionAction, isAdditionalFile = false) {
35
+ // Normalizar ruta para evitar duplicados
36
+ const normalizedPath = normalizeRuta(filePath);
37
+ // Agregar o actualizar el cambio pendiente
38
+ this.pendingChanges.set(normalizedPath, {
39
+ filePath: normalizedPath,
40
+ action,
41
+ timestamp: Date.now(),
42
+ extensionAction,
43
+ isAdditionalFile,
44
+ });
45
+ // Reiniciar el timer de debounce
46
+ this.resetDebounceTimer();
47
+ }
48
+ /**
49
+ * Reinicia el timer de debounce
50
+ */
51
+ resetDebounceTimer() {
52
+ if (this.debounceTimer) {
53
+ clearTimeout(this.debounceTimer);
54
+ }
55
+ this.debounceTimer = setTimeout(() => {
56
+ this.processPendingChanges();
57
+ }, this.DEBOUNCE_DELAY);
58
+ }
59
+ /**
60
+ * Procesa todos los cambios pendientes en batch
61
+ */
62
+ async processPendingChanges() {
63
+ if (this.isProcessing || this.pendingChanges.size === 0) {
64
+ return;
65
+ }
66
+ this.isProcessing = true;
67
+ const changes = Array.from(this.pendingChanges.values());
68
+ this.pendingChanges.clear();
69
+ try {
70
+ // Agrupar por tipo de acción para optimización
71
+ const deleteChanges = changes.filter(c => c.action === 'unlink');
72
+ const compileChanges = changes.filter(c => c.action === 'add' || c.action === 'change');
73
+ // Procesar eliminaciones primero
74
+ if (deleteChanges.length > 0) {
75
+ await this.processDeleteChanges(deleteChanges);
76
+ }
77
+ // Procesar compilaciones en batches
78
+ if (compileChanges.length > 0) {
79
+ await this.processCompileChanges(compileChanges);
80
+ }
81
+ }
82
+ catch (error) {
83
+ const chalkInstance = await loadChalk();
84
+ logger.error(chalkInstance.red(`🚩 Error procesando cambios en batch: ${error instanceof Error ? error.message : String(error)}`));
85
+ }
86
+ finally {
87
+ this.isProcessing = false;
88
+ // Si hay más cambios pendientes, procesarlos
89
+ if (this.pendingChanges.size > 0) {
90
+ this.resetDebounceTimer();
91
+ }
92
+ }
93
+ } /**
94
+ * Procesa cambios de eliminación
95
+ */
96
+ async processDeleteChanges(deleteChanges) {
97
+ for (const change of deleteChanges) {
98
+ if (change.isAdditionalFile) {
99
+ // ✨ Archivos adicionales: solo reload, sin eliminar del output
100
+ logger.info(`\n🗑️ Archivo adicional eliminado: ${change.filePath}`);
101
+ emitirCambios(this.browserSyncInstance, 'reloadFull', change.filePath);
102
+ }
103
+ else {
104
+ // Archivos compilables: eliminar del output
105
+ logger.info(`\n🗑️ Eliminando archivo compilado: ${change.filePath}`);
106
+ const result = await deleteFile(getOutputPath(change.filePath));
107
+ if (result) {
108
+ logger.info(`Archivo eliminado: ${change.filePath}`);
109
+ emitirCambios(this.browserSyncInstance, 'reloadFull', change.filePath);
110
+ }
111
+ }
112
+ }
113
+ }
114
+ /**
115
+ * Procesa cambios de compilación en paralelo con límite de concurrencia
116
+ */
117
+ async processCompileChanges(compileChanges) {
118
+ // ✨ NUEVO: Separar archivos adicionales de archivos compilables
119
+ const additionalFiles = compileChanges.filter(c => c.isAdditionalFile);
120
+ const compilableFiles = compileChanges.filter(c => !c.isAdditionalFile);
121
+ // ✨ Procesar archivos adicionales (solo reload, sin compilación)
122
+ if (additionalFiles.length > 0) {
123
+ await this.processAdditionalFiles(additionalFiles);
124
+ }
125
+ // Procesar archivos compilables normalmente
126
+ if (compilableFiles.length > 0) {
127
+ await this.processCompilableFiles(compilableFiles);
128
+ }
129
+ }
130
+ /**
131
+ * ✨ RENOMBRADO: Procesa archivos compilables
132
+ */
133
+ async processCompilableFiles(compilableFiles) {
134
+ const chalkInstance = await loadChalk();
135
+ // Procesar en batches para evitar sobrecarga
136
+ for (let i = 0; i < compilableFiles.length; i += this.BATCH_SIZE) {
137
+ const batch = compilableFiles.slice(i, i + this.BATCH_SIZE);
138
+ if (batch.length > 1) {
139
+ logger.info(chalkInstance.cyan(`📦 Procesando batch de ${batch.length} archivos compilables (${i + 1}-${Math.min(i + this.BATCH_SIZE, compilableFiles.length)} de ${compilableFiles.length})`));
140
+ }
141
+ const promises = batch.map(change => this.compileFile(change));
142
+ await Promise.allSettled(promises);
143
+ }
144
+ if (compilableFiles.length > 1) {
145
+ logger.info(chalkInstance.green(`✅ Batch completado: ${compilableFiles.length} archivos compilados`));
146
+ }
147
+ }
148
+ /**
149
+ * ✨ NUEVO: Procesa archivos adicionales (solo reloadFull)
150
+ */
151
+ async processAdditionalFiles(additionalFiles) {
152
+ const chalkInstance = await loadChalk();
153
+ logger.info(chalkInstance.blue(`🔄 Recargando ${additionalFiles.length} archivo(s) adicional(es) (sin compilación)`));
154
+ for (const change of additionalFiles) {
155
+ logger.info(`📄 Archivo adicional modificado: ${change.filePath}`);
156
+ // Solo hacer reloadFull, sin compilación
157
+ emitirCambios(this.browserSyncInstance, 'reloadFull', change.filePath);
158
+ }
159
+ }
160
+ /**
161
+ * Compila un archivo individual
162
+ */
163
+ async compileFile(change) {
164
+ try {
165
+ const result = await initCompile(change.filePath, true, 'watch');
166
+ if (result.success) {
167
+ let accion = result.action || change.extensionAction;
168
+ accion =
169
+ accion === 'extension' ? change.extensionAction : accion;
170
+ emitirCambios(this.browserSyncInstance, accion || 'reloadFull', result.output);
171
+ }
172
+ }
173
+ catch (error) {
174
+ const chalkInstance = await loadChalk();
175
+ logger.error(chalkInstance.red(`🚩 Error compilando ${change.filePath}: ${error instanceof Error ? error.message : String(error)}`));
176
+ }
177
+ }
178
+ /**
179
+ * Obtiene estadísticas del debouncer
180
+ */
181
+ getStats() {
182
+ return {
183
+ pendingChanges: this.pendingChanges.size,
184
+ isProcessing: this.isProcessing,
185
+ hasTimer: this.debounceTimer !== null,
186
+ };
187
+ }
188
+ }
189
+ // Instancia global del debouncer
190
+ const watchDebouncer = new WatchDebouncer();
191
+ // const cacheImportMap = new Map<string, string[]>();
192
+ // const cacheComponentMap = new Map<string, string[]>();
193
+ export async function cleanOutputDir(outputDir, primerInteraccion = true) {
194
+ try {
195
+ if (!outputDir) {
196
+ throw new Error('El directorio de salida no está definido');
197
+ }
198
+ if (primerInteraccion) {
199
+ const stats = await stat(outputDir).catch(() => null);
200
+ if (!stats || !stats.isDirectory()) {
201
+ logger.error(`🚩 El directorio de salida no existe o no es un directorio: ${outputDir}`);
202
+ return;
203
+ }
204
+ try {
205
+ if (env.yes === 'false') {
206
+ const chalkInstance = await loadChalk();
207
+ const answer = await promptUser('\n\n¿Estás seguro deseas limpiar la carpeta ' +
208
+ chalkInstance.yellow(outputDir) +
209
+ '? (s / N) : ');
210
+ if (answer.toLowerCase() !== 's') {
211
+ logger.info('🛑 Compilación cancelada por el usuario.');
212
+ process.exit(0);
213
+ }
214
+ }
215
+ }
216
+ catch (error) {
217
+ logger.error(`Error en la entrada del usuario: ${error}`);
218
+ process.exit(1);
219
+ }
220
+ }
221
+ const chalkInstance = await loadChalk();
222
+ logger.info(`🗑️ Limpiando directorio de salida: ${chalkInstance.yellow(outputDir)}\n`);
223
+ const items = await readdir(outputDir);
224
+ await Promise.all(items.map(async (item) => {
225
+ const itemPath = path.join(outputDir, item);
226
+ const itemStat = await stat(itemPath);
227
+ if (itemStat.isDirectory()) {
228
+ await rm(itemPath, { recursive: true });
229
+ }
230
+ else {
231
+ await unlink(itemPath);
232
+ }
233
+ }));
234
+ logger.info(`✅ Directorio limpiado: ${outputDir}`);
235
+ }
236
+ catch (error) {
237
+ logger.error(`🚩 Error al limpiar directorio de salida: ${error instanceof Error ? error.message : String(error)}`);
238
+ }
239
+ }
240
+ async function deleteFile(filePath) {
241
+ try {
242
+ await unlink(filePath);
243
+ return true;
244
+ }
245
+ catch (error) {
246
+ logger.error(`🚩 Error eliminando archivo ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
247
+ return false;
248
+ }
249
+ }
250
+ function getAction(ruta, extendsionWatch) {
251
+ const action = extendsionWatch
252
+ .filter((item) => item !== undefined)
253
+ .find(item => item.ext === ruta.split('.').pop())?.action;
254
+ return action || 'reloadFull';
255
+ }
256
+ /**
257
+ * Verifica si un archivo pertenece a las rutas adicionales (no compilables)
258
+ */
259
+ function isAdditionalWatchFile(filePath, additionalPatterns) {
260
+ if (!additionalPatterns || additionalPatterns.length === 0) {
261
+ return false;
262
+ }
263
+ const normalizedPath = normalizeRuta(filePath);
264
+ return additionalPatterns.some(pattern => {
265
+ // Normalizar el patrón también
266
+ const normalizedPattern = pattern.replace(/\\/g, '/');
267
+ return minimatch(normalizedPath, normalizedPattern);
268
+ });
269
+ }
270
+ export async function initChokidar(bs) {
271
+ try {
272
+ if (!env.PATH_SOURCE) {
273
+ logger.error('Error: La variable de entorno PATH_SOURCE no está definida.');
274
+ process.exit(1);
275
+ }
276
+ const watchJS = `${env.PATH_SOURCE}/**/*.js`;
277
+ const watchVue = `${env.PATH_SOURCE}/**/*.vue`;
278
+ const watchTS = `${env.PATH_SOURCE}/**/*.ts`;
279
+ const watchCJS = `${env.PATH_SOURCE}/**/*.cjs`;
280
+ const watchMJS = `${env.PATH_SOURCE}/**/*.mjs`;
281
+ //TODO: agregar watch para CSS
282
+ const watchAditional = JSON.parse(env.aditionalWatch || '[]');
283
+ let fileWatch = [
284
+ watchJS,
285
+ watchVue,
286
+ watchTS,
287
+ watchCJS,
288
+ watchMJS,
289
+ ...watchAditional,
290
+ ];
291
+ //extraer sólo las extesniones de fileWatch
292
+ const accionExtension = {
293
+ vue: 'HRMVue',
294
+ js: 'HRMHelper',
295
+ ts: 'HRMHelper',
296
+ cjs: 'HRMHelper',
297
+ mjs: 'HRMHelper',
298
+ };
299
+ const extendsionWatch = fileWatch.map(item => {
300
+ const ext = item.split('.').pop();
301
+ if (ext) {
302
+ return {
303
+ ext,
304
+ action: accionExtension[ext] ||
305
+ 'reloadFull',
306
+ };
307
+ }
308
+ });
309
+ if (extendsionWatch.length === 0 || extendsionWatch[0] === undefined) {
310
+ throw new Error('No se encontraron extensiones para observar');
311
+ }
312
+ const regExtExtension = new RegExp(`\\.(?!${extendsionWatch
313
+ .filter(item => item !== undefined)
314
+ .map(item => item.ext)
315
+ .join('$|')}$).+$`);
316
+ fileWatch = fileWatch.map(item => item.replace(/\/\*\*\//g, '/'));
317
+ const directories = new Map();
318
+ fileWatch.forEach(item => {
319
+ const dir = item.substring(0, item.lastIndexOf('/'));
320
+ if (!directories.has(dir)) {
321
+ directories.set(dir, []);
322
+ }
323
+ directories.get(dir).push(item);
324
+ });
325
+ const DirWatch = Array.from(directories.keys());
326
+ const watcher = chokidar.watch(DirWatch, {
327
+ persistent: true,
328
+ ignoreInitial: true,
329
+ ignored: regExtExtension,
330
+ });
331
+ watcher.on('ready', async () => {
332
+ const chalkInstance = await loadChalk();
333
+ logger.info(chalkInstance.green(`👀 : Listo para observar \n${fileWatch
334
+ .map((item) => `${item}`)
335
+ .join('\n')}\n`));
336
+ });
337
+ // ✨ CONFIGURAR: Establecer la instancia de browserSync en el debouncer
338
+ watchDebouncer.setBrowserSyncInstance(bs);
339
+ // ✨ OPTIMIZADO: Evento cuando se añade un archivo - Con debouncing
340
+ watcher.on('add', async (ruta) => {
341
+ const isAdditional = isAdditionalWatchFile(ruta, watchAditional);
342
+ const action = getAction(ruta, extendsionWatch.filter((item) => item !== undefined));
343
+ // Usar sistema de debouncing en lugar de compilación inmediata
344
+ watchDebouncer.addChange(ruta, 'add', action, isAdditional);
345
+ });
346
+ // ✨ OPTIMIZADO: Evento cuando se modifica un archivo - Con debouncing
347
+ watcher.on('change', async (ruta) => {
348
+ const isAdditional = isAdditionalWatchFile(ruta, watchAditional);
349
+ const action = getAction(ruta, extendsionWatch.filter((item) => item !== undefined));
350
+ // Usar sistema de debouncing en lugar de compilación inmediata
351
+ watchDebouncer.addChange(ruta, 'change', action, isAdditional);
352
+ });
353
+ // ✨ OPTIMIZADO: Evento cuando se elimina un archivo - Con debouncing
354
+ watcher.on('unlink', async (ruta) => {
355
+ const action = getAction(ruta, extendsionWatch.filter((item) => item !== undefined));
356
+ const isAdditional = isAdditionalWatchFile(ruta, watchAditional);
357
+ // Usar sistema de debouncing para eliminaciones también
358
+ watchDebouncer.addChange(ruta, 'unlink', action, isAdditional);
359
+ });
360
+ return watcher;
361
+ }
362
+ catch (error) {
363
+ logger.error(`🚩 :Error al iniciar watch: ${error instanceof Error ? error.message : String(error)}`);
364
+ process.exit(1);
365
+ }
366
+ }
367
+ //# sourceMappingURL=file-watcher.js.map
@@ -1,3 +1,4 @@
1
+ import * as process from 'node:process';
1
2
  class Logger {
2
3
  constructor() {
3
4
  // Bind console methods
@@ -1,4 +1,5 @@
1
1
  import { normalize, relative, resolve } from 'node:path';
2
+ import * as process from 'node:process';
2
3
  import { env } from 'node:process';
3
4
  import { pathToFileURL } from 'node:url';
4
5
  import { logger } from './logger.js';
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Lista centralizada de módulos excluidos de la resolución automática
3
+ * Estos módulos se mantienen con su importación original sin transformar
4
+ */
5
+ export const EXCLUDED_MODULES = new Set([
6
+ // Módulos de Vue.js que requieren resolución específica
7
+ 'vue/compiler-sfc',
8
+ 'vue/dist/vue.runtime.esm-bundler',
9
+ '@vue/compiler-sfc',
10
+ '@vue/compiler-dom',
11
+ '@vue/runtime-core',
12
+ '@vue/runtime-dom',
13
+ // Módulos de oxc-parser que tienen dependencias específicas de WASM
14
+ 'oxc-parser',
15
+ 'oxc-parser/wasm',
16
+ 'oxc-minify',
17
+ 'oxc-minify/browser',
18
+ '@oxc-parser/binding-wasm32-wasi',
19
+ '@oxc-minify/binding-wasm32-wasi',
20
+ // Módulos de TypeScript que pueden tener resoluciones complejas
21
+ 'typescript',
22
+ 'typescript/lib/typescript',
23
+ // Módulos de herramientas de build y utilidades que deben mantenerse originales
24
+ 'yargs',
25
+ 'yargs/helpers',
26
+ 'yargs-parser',
27
+ 'chalk',
28
+ 'browser-sync',
29
+ 'chokidar',
30
+ 'get-port',
31
+ 'execa',
32
+ 'find-root',
33
+ 'fs-extra',
34
+ 'minimatch', // ✅ Incluir minimatch aquí
35
+ ]);
36
+ //# sourceMappingURL=excluded-modules.js.map
@@ -1,39 +1,11 @@
1
1
  // Opción con librería '/node_modules/resolve/index.js' (npm install resolve)
2
2
  import fs, { readFileSync } from 'node:fs';
3
3
  import { dirname, join, relative } from 'node:path';
4
- import { env } from 'node:process';
5
- // import pkg from '/node_modules/enhanced-resolve/index.cjs';
4
+ import { cwd, env } from 'node:process';
5
+ // import pkg from '/node_modules/enhanced-resolve/lib/index.js';
6
6
  // import resolve from '/node_modules/resolve/index.js';
7
7
  import { logger } from '../servicios/logger.js';
8
- // Lista de módulos que deben ser excluidos de la resolución automática de rutas
9
- // Estos módulos se mantienen con su importación original sin transformar
10
- const EXCLUDED_MODULES = new Set([
11
- 'vue/compiler-sfc',
12
- 'vue/dist/vue.runtime.esm-bundler',
13
- '@vue/compiler-sfc',
14
- '@vue/compiler-dom',
15
- '@vue/runtime-core',
16
- '@vue/runtime-dom', // Módulos de oxc-parser que tienen dependencias específicas de WASM
17
- 'oxc-parser',
18
- 'oxc-parser/wasm',
19
- 'oxc-minify',
20
- 'oxc-minify/browser',
21
- '@oxc-parser/binding-wasm32-wasi',
22
- '@oxc-minify/binding-wasm32-wasi',
23
- // Módulos de TypeScript que pueden tener resoluciones complejas
24
- 'typescript',
25
- // Agregar más módulos problemáticos aquí según sea necesario
26
- 'yargs',
27
- 'yargs/helpers',
28
- 'yargs-parser',
29
- 'chalk',
30
- 'browser-sync',
31
- 'chokidar',
32
- 'get-port',
33
- 'execa',
34
- 'find-root',
35
- 'fs-extra',
36
- ]);
8
+ import { EXCLUDED_MODULES } from './excluded-modules.js';
37
9
  // function resolveESMWithLibrary(moduleName: string): string | null {
38
10
  // try {
39
11
  // // Resolver el módulo
@@ -58,7 +30,7 @@ const EXCLUDED_MODULES = new Set([
58
30
  // return null;
59
31
  // }
60
32
  // }
61
- // Opción con '/node_modules/enhanced-resolve/index.cjs' (webpack's resolver)
33
+ // Opción con '/node_modules/enhanced-resolve/lib/index.js' (webpack's resolver)
62
34
  // npm install enhanced-resolve
63
35
  // const { ResolverFactory } = pkg;
64
36
  // const resolver = ResolverFactory.createResolver({
@@ -128,9 +100,6 @@ function findOptimalESMVersion(moduleDir, entryPoint) {
128
100
  for (const pattern of priorityPatterns) {
129
101
  if (files.includes(pattern)) {
130
102
  const optimizedPath = join(dir, pattern).replace(/\\/g, '/');
131
- if (env.VERBOSE === 'true') {
132
- logger.info(`Versión optimizada encontrada: ${optimizedPath}`);
133
- }
134
103
  return optimizedPath;
135
104
  }
136
105
  } // Buscar archivos que contengan patrones ESM/browser dinámicamente
@@ -154,9 +123,6 @@ function findOptimalESMVersion(moduleDir, entryPoint) {
154
123
  !file.toLowerCase().includes('.min.'));
155
124
  if (devFiles.length > 0 && devFiles[0]) {
156
125
  const optimizedPath = join(dir, devFiles[0]).replace(/\\/g, '/');
157
- if (env.VERBOSE === 'true') {
158
- logger.info(`Versión ESM-Browser dev encontrada: ${optimizedPath}`);
159
- }
160
126
  return optimizedPath;
161
127
  }
162
128
  const prodFiles = esmBrowserCombined.filter(file => file.toLowerCase().includes('.prod.'));
@@ -260,7 +226,7 @@ function findOptimalESMVersion(moduleDir, entryPoint) {
260
226
  // Función mejorada para detectar automáticamente entry points browser-compatible
261
227
  function simpleESMResolver(moduleName) {
262
228
  try {
263
- const nodeModulesPath = join(process.cwd(), 'node_modules', moduleName);
229
+ const nodeModulesPath = join(cwd(), 'node_modules', moduleName);
264
230
  let packagePath;
265
231
  let packageJson;
266
232
  try {
@@ -370,7 +336,8 @@ function simpleESMResolver(moduleName) {
370
336
  if (env.VERBOSE === 'true')
371
337
  logger.info(`Módulo ${moduleName} usa imports privados:`, privateImports.map(m => m[1]));
372
338
  // Si usa imports privados, asegurarnos de que estén disponibles
373
- for (const [, importPath] of privateImports) {
339
+ for (const match of privateImports) {
340
+ const [, importPath] = match;
374
341
  if (!importMap.has(importPath)) {
375
342
  if (env.VERBOSE === 'true')
376
343
  logger.warn(`Import privado no resuelto: ${importPath} en ${moduleName}`);
@@ -381,8 +348,6 @@ function simpleESMResolver(moduleName) {
381
348
  }
382
349
  // Verificar que el archivo existe
383
350
  if (!fs.existsSync(finalPath)) {
384
- if (env.VERBOSE === 'true')
385
- logger.warn(`⚠️ Archivo no existe: ${finalPath}, buscando alternativas...`);
386
351
  // Intentar alternativas comunes
387
352
  const alternatives = [
388
353
  entryPoint,
@@ -422,7 +387,7 @@ function getNodeModulesRelativePath(fullPath, _fromFile) {
422
387
  return '/' + relativePath;
423
388
  }
424
389
  // Para rutas que no están en node_modules, convertir a ruta absoluta desde la raíz
425
- let rel = relative(process.cwd(), fullPath).replace(/\\/g, '/');
390
+ let rel = relative(cwd(), fullPath).replace(/\\/g, '/');
426
391
  if (!rel)
427
392
  rel = '.';
428
393
  // Convertir a ruta absoluta desde la raíz
@@ -434,8 +399,6 @@ function getNodeModulesRelativePath(fullPath, _fromFile) {
434
399
  export function getModulePath(moduleName, fromFile) {
435
400
  // Verificar si el módulo está en la lista de excluidos
436
401
  if (EXCLUDED_MODULES.has(moduleName)) {
437
- if (env.VERBOSE === 'true')
438
- logger.info(`Módulo ${moduleName} está en la lista de excluidos, manteniendo importación original`);
439
402
  return null; // Retornar null para mantener la importación original
440
403
  }
441
404
  return getNodeModulesRelativePath(simpleESMResolver(moduleName), fromFile);
@@ -444,8 +407,6 @@ export function getModulePath(moduleName, fromFile) {
444
407
  export function getModuleSubPath(moduleName, fromFile) {
445
408
  // Verificar si el módulo está en la lista de excluidos
446
409
  if (EXCLUDED_MODULES.has(moduleName)) {
447
- if (env.VERBOSE === 'true')
448
- logger.info(`Módulo ${moduleName} está en la lista de excluidos, manteniendo importación original`);
449
410
  return null; // Retornar null para mantener la importación original
450
411
  } // Si contiene '/', es un subpath
451
412
  if (moduleName.includes('/')) {
@@ -456,7 +417,7 @@ export function getModuleSubPath(moduleName, fromFile) {
456
417
  return null;
457
418
  }
458
419
  try {
459
- const nodeModulesPath = join(process.cwd(), 'node_modules', packageName);
420
+ const nodeModulesPath = join(cwd(), 'node_modules', packageName);
460
421
  const packagePath = join(nodeModulesPath, 'package.json');
461
422
  if (!fs.existsSync(packagePath)) {
462
423
  return null;
@@ -1,4 +1,4 @@
1
- import { stdin as input, stdout as output } from 'node:process';
1
+ import process, { stdin as input, stdout as output } from 'node:process';
2
2
  import * as readline from 'node:readline/promises';
3
3
  import { logger } from '../servicios/logger.js';
4
4
  export async function promptUser(question, timeout = 30000) {
@@ -1,19 +1,38 @@
1
- import { createRequire } from 'node:module';
2
- import path from 'node:path';
1
+ import * as path from 'node:path';
2
+ import * as process from 'node:process';
3
3
  import findRoot from 'find-root';
4
4
  import fs from 'fs-extra';
5
+ // Función helper para resolver módulos sin createRequire
6
+ function resolveModule(moduleName, paths) {
7
+ for (const searchPath of paths) {
8
+ try {
9
+ const nodeModulesPath = path.join(searchPath, 'node_modules', moduleName);
10
+ if (fs.existsSync(nodeModulesPath)) {
11
+ return nodeModulesPath;
12
+ }
13
+ }
14
+ catch {
15
+ // Continuar con el siguiente path
16
+ }
17
+ }
18
+ throw new Error(`Cannot resolve module ${moduleName} from paths: ${paths.join(', ')}`);
19
+ }
5
20
  export function resolveBin(moduleName, { executable = moduleName, paths = [process.cwd()], } = {}) {
6
21
  let rootDir;
7
22
  try {
8
- const customRequire = createRequire(__filename);
9
- const resolved = customRequire.resolve(moduleName, { paths });
23
+ const resolved = resolveModule(moduleName, paths);
10
24
  rootDir = findRoot(resolved);
11
25
  }
12
- catch (e) {
13
- const modJson = require.resolve(`${moduleName}/package.json`, {
14
- paths,
15
- });
16
- rootDir = path.dirname(modJson);
26
+ catch {
27
+ // Intentar resolver package.json directamente
28
+ const basePath = paths[0] || process.cwd();
29
+ const packagePath = path.join(basePath, 'node_modules', moduleName, 'package.json');
30
+ if (fs.existsSync(packagePath)) {
31
+ rootDir = path.dirname(packagePath);
32
+ }
33
+ else {
34
+ throw new Error(`Cannot resolve module ${moduleName}`);
35
+ }
17
36
  }
18
37
  const packageJsonPath = path.join(rootDir, 'package.json');
19
38
  const packageJson = fs.readJsonSync(packageJsonPath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "versacompiler",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
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": {
@@ -19,7 +19,7 @@
19
19
  "dev": "tsx --watch src/main.ts --watch --verbose --tailwind",
20
20
  "compile": "tsx src/main.ts --all",
21
21
  "test": "jest --config jest.config.js",
22
- "build": "tsx src/main.ts --all -t --clean -y",
22
+ "build": "tsx src/main.ts --all -t --cc --co -y --verbose",
23
23
  "lint": "oxlint --fix --config .oxlintrc.json",
24
24
  "lint:eslint": "eslint --ext .js,.ts,.vue src/ --fix",
25
25
  "perf": "scripts\\run-performance.bat",
@@ -52,6 +52,7 @@
52
52
  "find-root": "^1.1.0",
53
53
  "fs-extra": "^11.3.0",
54
54
  "get-port": "^7.1.0",
55
+ "minimatch": "^10.0.1",
55
56
  "oxc-minify": "^0.72.3",
56
57
  "oxc-parser": "^0.72.3",
57
58
  "oxc-transform": "^0.72.3",
@@ -69,7 +70,7 @@
69
70
  "@types/fs-extra": "^11.0.4",
70
71
  "@types/jest": "^29.5.14",
71
72
  "@types/mocha": "^10.0.10",
72
- "@types/node": "^22.15.30",
73
+ "@types/node": "^24.0.0",
73
74
  "@types/resolve": "^1.20.6",
74
75
  "@types/yargs": "^17.0.33",
75
76
  "@typescript-eslint/eslint-plugin": "^8.34.0",
@@ -80,15 +81,15 @@
80
81
  "eslint": "^9.28.0",
81
82
  "eslint-import-resolver-typescript": "^4.4.3",
82
83
  "eslint-plugin-import": "^2.31.0",
83
- "eslint-plugin-oxlint": "^0.17.0",
84
+ "eslint-plugin-oxlint": "^1.0.0",
84
85
  "eslint-plugin-promise": "^7.2.1",
85
86
  "eslint-plugin-unicorn": "^59.0.1",
86
87
  "eslint-plugin-vue": "^10.2.0",
87
88
  "happy-dom": "^17.6.3",
88
89
  "jest": "^29.7.0",
89
- "jest-environment-jsdom": "30.0.0-beta.3",
90
- "jest-environment-node": "30.0.0-beta.3",
91
- "oxlint": "^0.17.0",
90
+ "jest-environment-jsdom": "30.0.0",
91
+ "jest-environment-node": "30.0.0",
92
+ "oxlint": "^1.0.0",
92
93
  "prettier": "3.5.3",
93
94
  "rimraf": "^6.0.1",
94
95
  "sweetalert2": "^11.22.0",