versacompiler 2.1.0 → 2.2.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 (41) hide show
  1. package/README.md +1 -1
  2. package/dist/compiler/compile.js +2520 -25
  3. package/dist/compiler/error-reporter.js +467 -38
  4. package/dist/compiler/linter.js +72 -1
  5. package/dist/compiler/minify.js +272 -1
  6. package/dist/compiler/minifyTemplate.js +230 -1
  7. package/dist/compiler/module-resolution-optimizer.js +844 -1
  8. package/dist/compiler/parser.js +336 -1
  9. package/dist/compiler/performance-monitor.js +204 -56
  10. package/dist/compiler/tailwindcss.js +39 -1
  11. package/dist/compiler/transform-optimizer.js +392 -1
  12. package/dist/compiler/transformTStoJS.js +16 -1
  13. package/dist/compiler/transforms.js +554 -1
  14. package/dist/compiler/typescript-compiler.js +172 -2
  15. package/dist/compiler/typescript-error-parser.js +281 -10
  16. package/dist/compiler/typescript-manager.js +304 -2
  17. package/dist/compiler/typescript-sync-validator.js +295 -31
  18. package/dist/compiler/typescript-worker-pool.js +936 -1
  19. package/dist/compiler/typescript-worker-thread.cjs +466 -22
  20. package/dist/compiler/typescript-worker.js +339 -1
  21. package/dist/compiler/vuejs.js +396 -37
  22. package/dist/hrm/VueHRM.js +359 -1
  23. package/dist/hrm/errorScreen.js +83 -1
  24. package/dist/hrm/getInstanciaVue.js +313 -1
  25. package/dist/hrm/initHRM.js +586 -1
  26. package/dist/main.js +353 -7
  27. package/dist/servicios/browserSync.js +589 -2
  28. package/dist/servicios/file-watcher.js +425 -4
  29. package/dist/servicios/logger.js +63 -3
  30. package/dist/servicios/readConfig.js +399 -53
  31. package/dist/utils/excluded-modules.js +37 -1
  32. package/dist/utils/module-resolver.js +466 -1
  33. package/dist/utils/promptUser.js +48 -2
  34. package/dist/utils/proxyValidator.js +68 -1
  35. package/dist/utils/resolve-bin.js +58 -1
  36. package/dist/utils/utils.js +21 -1
  37. package/dist/utils/vue-types-setup.js +435 -241
  38. package/dist/wrappers/eslint-node.js +1 -1
  39. package/dist/wrappers/oxlint-node.js +122 -1
  40. package/dist/wrappers/tailwind-node.js +94 -1
  41. package/package.json +106 -103
@@ -1,4 +1,425 @@
1
- import{readdir as e,rm as r,stat as i,unlink as a}from"node:fs/promises";import o from"node:path";import s,{env as c}from"node:process";import*as l from"chokidar";import{minimatch as u}from"minimatch";import{getOutputPath as d,initCompile as f,normalizeRuta as p}from"../compiler/compile.js";import{promptUser as m}from"../utils/promptUser.js";import{emitirCambios as h}from"./browserSync.js";import{logger as g}from"./logger.js";let _;async function v(){return _||(_=(await import(`chalk`)).default),_}class y{pendingChanges=new Map;debounceTimer=null;DEBOUNCE_DELAY=100;BATCH_SIZE=10;isProcessing=!1;browserSyncInstance=null;setBrowserSyncInstance(e){this.browserSyncInstance=e}cleanup(){this.debounceTimer&&(clearTimeout(this.debounceTimer),this.debounceTimer=null),this.pendingChanges.clear(),this.isProcessing=!1,this.browserSyncInstance=null}addChange(e,r,i,a=!1){let o=p(e);this.pendingChanges.set(o,{filePath:o,action:r,timestamp:Date.now(),extensionAction:i,isAdditionalFile:a}),this.resetDebounceTimer()}resetDebounceTimer(){this.debounceTimer&&clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>{this.processPendingChanges()},this.DEBOUNCE_DELAY)}async processPendingChanges(){if(this.isProcessing||this.pendingChanges.size===0)return;this.isProcessing=!0;let e=Array.from(this.pendingChanges.values());this.pendingChanges.clear();try{let r=e.filter(e=>e.action===`unlink`),i=e.filter(e=>e.action===`add`||e.action===`change`);r.length>0&&await this.processDeleteChanges(r),i.length>0&&await this.processCompileChanges(i)}catch(e){let r=await v();g.error(r.red(`🚩 Error procesando cambios en batch: ${e instanceof Error?e.message:String(e)}`))}finally{this.isProcessing=!1,this.pendingChanges.size>0&&this.resetDebounceTimer()}}async processDeleteChanges(e){for(let r of e)r.isAdditionalFile?(g.info(`\n🗑️ Archivo adicional eliminado: ${r.filePath}`),h(this.browserSyncInstance,`reloadFull`,r.filePath)):(g.info(`\n🗑️ Eliminando archivo compilado: ${r.filePath}`),await S(d(r.filePath))&&(g.info(`Archivo eliminado: ${r.filePath}`),h(this.browserSyncInstance,`reloadFull`,r.filePath)))}async processCompileChanges(e){let r=e.filter(e=>e.isAdditionalFile),i=e.filter(e=>!e.isAdditionalFile);r.length>0&&await this.processAdditionalFiles(r),i.length>0&&await this.processCompilableFiles(i)}async processCompilableFiles(e){let r=await v();for(let i=0;i<e.length;i+=this.BATCH_SIZE){let a=e.slice(i,i+this.BATCH_SIZE);a.length>1&&g.info(r.cyan(`📦 Procesando batch de ${a.length} archivos compilables (${i+1}-${Math.min(i+this.BATCH_SIZE,e.length)} de ${e.length})`));let o=a.map(e=>this.compileFile(e));await Promise.allSettled(o)}e.length>1&&g.info(r.green(`✅ Batch completado: ${e.length} archivos compilados`))}async processAdditionalFiles(e){let r=await v();g.info(r.blue(`🔄 Recargando ${e.length} archivo(s) adicional(es) (sin compilación)`));for(let r of e)g.info(`📄 Archivo adicional modificado: ${r.filePath}`),h(this.browserSyncInstance,`reloadFull`,r.filePath)}async compileFile(e){try{let r=await f(e.filePath,!0,`watch`);if(r.success){let i=r.action||e.extensionAction;i=i===`extension`?e.extensionAction:i,h(this.browserSyncInstance,i||`reloadFull`,r.output)}}catch(r){let i=await v();g.error(i.red(`🚩 Error compilando ${e.filePath}: ${r instanceof Error?r.message:String(r)}`))}}getStats(){return{pendingChanges:this.pendingChanges.size,isProcessing:this.isProcessing,hasTimer:this.debounceTimer!==null}}}const b=new y;export async function cleanOutputDir(l,u=!0){try{if(!l)throw Error(`El directorio de salida no está definido`);if(u){let e=await i(l).catch(()=>null);if(!e||!e.isDirectory()){g.error(`🚩 El directorio de salida no existe o no es un directorio: ${l}`);return}try{if(c.yes===`false`&&(await m(`
2
-
3
- ¿Estás seguro deseas limpiar la carpeta `+(await v()).yellow(l)+`? (s / N) : `)).toLowerCase()!==`s`){g.info(`🛑 Compilación cancelada por el usuario.`),s.env.NODE_ENV!==`test`&&s.exit(0);return}}catch(e){throw g.error(`Error en la entrada del usuario: ${e}`),s.env.NODE_ENV!==`test`&&s.exit(1),e}}let d=await v();g.info(`🗑️ Limpiando directorio de salida: ${d.yellow(l)}\n`);let f=await e(l);await Promise.all(f.map(async e=>{let s=o.join(l,e);(await i(s)).isDirectory()?await r(s,{recursive:!0}):await a(s)})),g.info(`✅ Directorio limpiado: ${l}`)}catch(e){g.error(`🚩 Error al limpiar directorio de salida: ${e instanceof Error?e.message:String(e)}`)}}async function S(e){try{return await a(e),!0}catch(r){return g.error(`🚩 Error eliminando archivo ${e}: ${r instanceof Error?r.message:String(r)}`),!1}}function C(e,r){return r.filter(e=>e!==void 0).find(r=>r.ext===e.split(`.`).pop())?.action||`reloadFull`}function w(e,r){if(!r||r.length===0)return!1;let i=p(e);return r.some(e=>u(i,e.replace(/\\/g,`/`)))}export async function initChokidar(e){try{if(!c.PATH_SOURCE)throw g.error(`Error: La variable de entorno PATH_SOURCE no está definida.`),s.env.NODE_ENV!==`test`&&s.exit(1),Error(`PATH_SOURCE no está definida`);let r=`${c.PATH_SOURCE}/**/*.js`,i=`${c.PATH_SOURCE}/**/*.vue`,a=`${c.PATH_SOURCE}/**/*.ts`,o=`${c.PATH_SOURCE}/**/*.cjs`,u=`${c.PATH_SOURCE}/**/*.mjs`,d=JSON.parse(c.aditionalWatch||`[]`),f=[r,i,a,o,u,...d],p={vue:`HRMVue`,js:`HRMHelper`,ts:`HRMHelper`,cjs:`HRMHelper`,mjs:`HRMHelper`},m=f.map(e=>{let r=e.split(`.`).pop();if(r)return{ext:r,action:p[r]||`reloadFull`}});if(m.length===0||m[0]===void 0)throw Error(`No se encontraron extensiones para observar`);let h=RegExp(`\\.(?!${m.filter(e=>e!==void 0).map(e=>e.ext).join(`$|`)}$).+$`);f=f.map(e=>e.replace(/\/\*\*\//g,`/`));let _=new Map;f.forEach(e=>{let r=e.substring(0,e.lastIndexOf(`/`));_.has(r)||_.set(r,[]),_.get(r).push(e)});let y=Array.from(_.keys()),x=l.watch(y,{persistent:!0,ignoreInitial:!0,ignored:h});return x.on(`ready`,async()=>{let e=await v();g.info(e.green(`👀 : Listo para observar \n${f.map(e=>`${e}`).join(`
4
- `)}\n`))}),b.setBrowserSyncInstance(e),x.on(`add`,async e=>{let r=w(e,d),i=C(e,m.filter(e=>e!==void 0));b.addChange(e,`add`,i,r)}),x.on(`change`,async e=>{let r=w(e,d),i=C(e,m.filter(e=>e!==void 0));b.addChange(e,`change`,i,r)}),x.on(`unlink`,async e=>{let r=C(e,m.filter(e=>e!==void 0)),i=w(e,d);b.addChange(e,`unlink`,r,i)}),x}catch(e){throw g.error(`🚩 :Error al iniciar watch: ${e instanceof Error?e.message:String(e)}`),s.env.NODE_ENV!==`test`&&s.exit(1),e}}export async function cleanupWatcher(e){try{console.log(`[FileWatcher] Limpiando recursos...`),b.cleanup(),e&&await e.close(),console.log(`[FileWatcher] Recursos limpiados correctamente`)}catch(e){console.error(`[FileWatcher] Error al limpiar recursos:`,e instanceof Error?e.message:String(e))}}
1
+ import { readdir, rm, stat, unlink } from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import * as process from 'node:process';
4
+ const { env } = process;
5
+ import * as chokidar from 'chokidar';
6
+ import { minimatch } from 'minimatch';
7
+ import { getOutputPath, initCompile, normalizeRuta } from '../compiler/compile.js';
8
+ import { promptUser } from '../utils/promptUser.js';
9
+ import { emitirCambios } from './browserSync.js';
10
+ import { logger } from './logger.js';
11
+ // Lazy loading para chalk
12
+ let chalk;
13
+ async function loadChalk() {
14
+ if (!chalk) {
15
+ chalk = (await import('chalk')).default;
16
+ }
17
+ return chalk;
18
+ }
19
+ class WatchDebouncer {
20
+ pendingChanges = new Map();
21
+ debounceTimer = null;
22
+ DEBOUNCE_DELAY = 50; // ✨ OPTIMIZACIÓN: 50ms para hot reload más responsive
23
+ BATCH_SIZE = 10; // Máximo archivos por batch
24
+ isProcessing = false;
25
+ browserSyncInstance = null; // ✨ Almacenar referencia a browserSync
26
+ /**
27
+ * Establece la instancia de browserSync
28
+ */
29
+ setBrowserSyncInstance(bs) {
30
+ this.browserSyncInstance = bs;
31
+ }
32
+ /**
33
+ * ✨ FIX #3: Limpia todos los recursos del debouncer
34
+ */
35
+ cleanup() {
36
+ if (this.debounceTimer) {
37
+ clearTimeout(this.debounceTimer);
38
+ this.debounceTimer = null;
39
+ }
40
+ this.pendingChanges.clear();
41
+ this.isProcessing = false;
42
+ this.browserSyncInstance = null;
43
+ }
44
+ /**
45
+ * Añade un cambio al sistema de debouncing
46
+ */
47
+ addChange(filePath, action, extensionAction, isAdditionalFile = false) {
48
+ // Normalizar ruta para evitar duplicados
49
+ const normalizedPath = normalizeRuta(filePath);
50
+ // Agregar o actualizar el cambio pendiente
51
+ this.pendingChanges.set(normalizedPath, {
52
+ filePath: normalizedPath,
53
+ action,
54
+ timestamp: Date.now(),
55
+ extensionAction,
56
+ isAdditionalFile,
57
+ });
58
+ // Reiniciar el timer de debounce
59
+ this.resetDebounceTimer();
60
+ }
61
+ /**
62
+ * Reinicia el timer de debounce
63
+ */
64
+ resetDebounceTimer() {
65
+ if (this.debounceTimer) {
66
+ clearTimeout(this.debounceTimer);
67
+ }
68
+ this.debounceTimer = setTimeout(() => {
69
+ this.processPendingChanges();
70
+ }, this.DEBOUNCE_DELAY);
71
+ }
72
+ /**
73
+ * Procesa todos los cambios pendientes en batch
74
+ */
75
+ async processPendingChanges() {
76
+ if (this.isProcessing || this.pendingChanges.size === 0) {
77
+ return;
78
+ }
79
+ this.isProcessing = true;
80
+ const changes = Array.from(this.pendingChanges.values());
81
+ this.pendingChanges.clear();
82
+ try {
83
+ // Agrupar por tipo de acción para optimización
84
+ const deleteChanges = changes.filter(c => c.action === 'unlink');
85
+ const compileChanges = changes.filter(c => c.action === 'add' || c.action === 'change');
86
+ // Procesar eliminaciones primero
87
+ if (deleteChanges.length > 0) {
88
+ await this.processDeleteChanges(deleteChanges);
89
+ }
90
+ // Procesar compilaciones en batches
91
+ if (compileChanges.length > 0) {
92
+ await this.processCompileChanges(compileChanges);
93
+ }
94
+ }
95
+ catch (error) {
96
+ const chalkInstance = await loadChalk();
97
+ logger.error(chalkInstance.red(`🚩 Error procesando cambios en batch: ${error instanceof Error ? error.message : String(error)}`));
98
+ }
99
+ finally {
100
+ this.isProcessing = false;
101
+ // Si hay más cambios pendientes, procesarlos
102
+ if (this.pendingChanges.size > 0) {
103
+ this.resetDebounceTimer();
104
+ }
105
+ }
106
+ } /**
107
+ * Procesa cambios de eliminación
108
+ */
109
+ async processDeleteChanges(deleteChanges) {
110
+ for (const change of deleteChanges) {
111
+ if (change.isAdditionalFile) {
112
+ // ✨ Archivos adicionales: solo reload, sin eliminar del output
113
+ logger.info(`\n🗑️ Archivo adicional eliminado: ${change.filePath}`);
114
+ emitirCambios(this.browserSyncInstance, 'reloadFull', change.filePath);
115
+ }
116
+ else {
117
+ // Archivos compilables: eliminar del output
118
+ logger.info(`\n🗑️ Eliminando archivo compilado: ${change.filePath}`);
119
+ const result = await deleteFile(getOutputPath(change.filePath));
120
+ if (result) {
121
+ logger.info(`Archivo eliminado: ${change.filePath}`);
122
+ emitirCambios(this.browserSyncInstance, 'reloadFull', change.filePath);
123
+ }
124
+ }
125
+ }
126
+ }
127
+ /**
128
+ * Procesa cambios de compilación en paralelo con límite de concurrencia
129
+ */
130
+ async processCompileChanges(compileChanges) {
131
+ // ✨ NUEVO: Separar archivos adicionales de archivos compilables
132
+ const additionalFiles = compileChanges.filter(c => c.isAdditionalFile);
133
+ const compilableFiles = compileChanges.filter(c => !c.isAdditionalFile);
134
+ // ✨ Procesar archivos adicionales (solo reload, sin compilación)
135
+ if (additionalFiles.length > 0) {
136
+ await this.processAdditionalFiles(additionalFiles);
137
+ }
138
+ // Procesar archivos compilables normalmente
139
+ if (compilableFiles.length > 0) {
140
+ await this.processCompilableFiles(compilableFiles);
141
+ }
142
+ }
143
+ /**
144
+ * ✨ RENOMBRADO: Procesa archivos compilables
145
+ */
146
+ async processCompilableFiles(compilableFiles) {
147
+ const chalkInstance = await loadChalk();
148
+ // Procesar en batches para evitar sobrecarga
149
+ for (let i = 0; i < compilableFiles.length; i += this.BATCH_SIZE) {
150
+ const batch = compilableFiles.slice(i, i + this.BATCH_SIZE);
151
+ if (batch.length > 1) {
152
+ logger.info(chalkInstance.cyan(`📦 Procesando batch de ${batch.length} archivos compilables (${i + 1}-${Math.min(i + this.BATCH_SIZE, compilableFiles.length)} de ${compilableFiles.length})`));
153
+ }
154
+ const promises = batch.map(change => this.compileFile(change));
155
+ await Promise.allSettled(promises);
156
+ }
157
+ if (compilableFiles.length > 1) {
158
+ logger.info(chalkInstance.green(`✅ Batch completado: ${compilableFiles.length} archivos compilados`));
159
+ }
160
+ }
161
+ /**
162
+ * ✨ NUEVO: Procesa archivos adicionales (solo reloadFull)
163
+ */
164
+ async processAdditionalFiles(additionalFiles) {
165
+ const chalkInstance = await loadChalk();
166
+ logger.info(chalkInstance.blue(`🔄 Recargando ${additionalFiles.length} archivo(s) adicional(es) (sin compilación)`));
167
+ for (const change of additionalFiles) {
168
+ logger.info(`📄 Archivo adicional modificado: ${change.filePath}`);
169
+ // Solo hacer reloadFull, sin compilación
170
+ emitirCambios(this.browserSyncInstance, 'reloadFull', change.filePath);
171
+ }
172
+ }
173
+ /**
174
+ * Compila un archivo individual
175
+ */
176
+ async compileFile(change) {
177
+ try {
178
+ const result = await initCompile(change.filePath, true, 'watch');
179
+ if (result.success) {
180
+ let accion = result.action || change.extensionAction;
181
+ accion =
182
+ accion === 'extension' ? change.extensionAction : accion;
183
+ emitirCambios(this.browserSyncInstance, accion || 'reloadFull', result.output);
184
+ }
185
+ }
186
+ catch (error) {
187
+ const chalkInstance = await loadChalk();
188
+ logger.error(chalkInstance.red(`🚩 Error compilando ${change.filePath}: ${error instanceof Error ? error.message : String(error)}`));
189
+ }
190
+ }
191
+ /**
192
+ * Obtiene estadísticas del debouncer
193
+ */
194
+ getStats() {
195
+ return {
196
+ pendingChanges: this.pendingChanges.size,
197
+ isProcessing: this.isProcessing,
198
+ hasTimer: this.debounceTimer !== null,
199
+ };
200
+ }
201
+ }
202
+ // Instancia global del debouncer
203
+ const watchDebouncer = new WatchDebouncer();
204
+ // const cacheImportMap = new Map<string, string[]>();
205
+ // const cacheComponentMap = new Map<string, string[]>();
206
+ export async function cleanOutputDir(outputDir, primerInteraccion = true) {
207
+ try {
208
+ if (!outputDir) {
209
+ throw new Error('El directorio de salida no está definido');
210
+ }
211
+ if (primerInteraccion) {
212
+ const stats = await stat(outputDir).catch(() => null);
213
+ if (!stats || !stats.isDirectory()) {
214
+ logger.error(`🚩 El directorio de salida no existe o no es un directorio: ${outputDir}`);
215
+ return;
216
+ }
217
+ try {
218
+ if (env.yes === 'false') {
219
+ const chalkInstance = await loadChalk();
220
+ const answer = await promptUser('\n\n¿Estás seguro deseas limpiar la carpeta ' +
221
+ chalkInstance.yellow(outputDir) +
222
+ '? (s / N) : ');
223
+ if (answer.toLowerCase() !== 's') {
224
+ logger.info('🛑 Compilación cancelada por el usuario.');
225
+ if (process.env.NODE_ENV !== 'test') {
226
+ process.exit(0);
227
+ }
228
+ return;
229
+ }
230
+ }
231
+ }
232
+ catch (error) {
233
+ logger.error(`Error en la entrada del usuario: ${error}`);
234
+ if (process.env.NODE_ENV !== 'test') {
235
+ process.exit(1);
236
+ }
237
+ throw error;
238
+ }
239
+ }
240
+ const chalkInstance = await loadChalk();
241
+ logger.info(`🗑️ Limpiando directorio de salida: ${chalkInstance.yellow(outputDir)}\n`);
242
+ const items = await readdir(outputDir);
243
+ await Promise.all(items.map(async (item) => {
244
+ const itemPath = path.join(outputDir, item);
245
+ const itemStat = await stat(itemPath);
246
+ if (itemStat.isDirectory()) {
247
+ await rm(itemPath, { recursive: true });
248
+ }
249
+ else {
250
+ await unlink(itemPath);
251
+ }
252
+ }));
253
+ logger.info(`✅ Directorio limpiado: ${outputDir}`);
254
+ }
255
+ catch (error) {
256
+ logger.error(`🚩 Error al limpiar directorio de salida: ${error instanceof Error ? error.message : String(error)}`);
257
+ }
258
+ }
259
+ async function deleteFile(filePath) {
260
+ try {
261
+ await unlink(filePath);
262
+ return true;
263
+ }
264
+ catch (error) {
265
+ logger.error(`🚩 Error eliminando archivo ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
266
+ return false;
267
+ }
268
+ }
269
+ function getAction(ruta, extendsionWatch) {
270
+ const action = extendsionWatch
271
+ .filter((item) => item !== undefined)
272
+ .find(item => item.ext === ruta.split('.').pop())?.action;
273
+ return action || 'reloadFull';
274
+ }
275
+ /**
276
+ * Verifica si un archivo pertenece a las rutas adicionales (no compilables)
277
+ */
278
+ function isAdditionalWatchFile(filePath, additionalPatterns) {
279
+ if (!additionalPatterns || additionalPatterns.length === 0) {
280
+ return false;
281
+ }
282
+ const normalizedPath = normalizeRuta(filePath);
283
+ return additionalPatterns.some(pattern => {
284
+ // Normalizar el patrón también
285
+ const normalizedPattern = pattern.replace(/\\/g, '/');
286
+ return minimatch(normalizedPath, normalizedPattern);
287
+ });
288
+ }
289
+ export async function initChokidar(bs) {
290
+ try {
291
+ if (!env.PATH_SOURCE) {
292
+ logger.error('Error: La variable de entorno PATH_SOURCE no está definida.');
293
+ if (process.env.NODE_ENV !== 'test') {
294
+ process.exit(1);
295
+ }
296
+ throw new Error('PATH_SOURCE no está definida');
297
+ }
298
+ const watchJS = `${env.PATH_SOURCE}/**/*.js`;
299
+ const watchVue = `${env.PATH_SOURCE}/**/*.vue`;
300
+ const watchTS = `${env.PATH_SOURCE}/**/*.ts`;
301
+ const watchCJS = `${env.PATH_SOURCE}/**/*.cjs`;
302
+ const watchMJS = `${env.PATH_SOURCE}/**/*.mjs`;
303
+ //TODO: agregar watch para CSS
304
+ const watchAditional = JSON.parse(env.aditionalWatch || '[]');
305
+ let fileWatch = [
306
+ watchJS,
307
+ watchVue,
308
+ watchTS,
309
+ watchCJS,
310
+ watchMJS,
311
+ ...watchAditional,
312
+ ];
313
+ //extraer sólo las extesniones de fileWatch
314
+ const accionExtension = {
315
+ vue: 'HRMVue',
316
+ js: 'HRMHelper',
317
+ ts: 'HRMHelper',
318
+ cjs: 'HRMHelper',
319
+ mjs: 'HRMHelper',
320
+ };
321
+ const extendsionWatch = fileWatch.map(item => {
322
+ const ext = item.split('.').pop();
323
+ if (ext) {
324
+ return {
325
+ ext,
326
+ action: accionExtension[ext] ||
327
+ 'reloadFull',
328
+ };
329
+ }
330
+ });
331
+ if (extendsionWatch.length === 0 || extendsionWatch[0] === undefined) {
332
+ throw new Error('No se encontraron extensiones para observar');
333
+ }
334
+ const regExtExtension = new RegExp(`\\.(?!${extendsionWatch
335
+ .filter(item => item !== undefined)
336
+ .map(item => item.ext)
337
+ .join('$|')}$).+$`);
338
+ fileWatch = fileWatch.map(item => item.replace(/\/\*\*\//g, '/'));
339
+ const directories = new Map();
340
+ fileWatch.forEach(item => {
341
+ const dir = item.substring(0, item.lastIndexOf('/'));
342
+ if (!directories.has(dir)) {
343
+ directories.set(dir, []);
344
+ }
345
+ directories.get(dir).push(item);
346
+ });
347
+ const DirWatch = Array.from(directories.keys());
348
+ const watcher = chokidar.watch(DirWatch, {
349
+ persistent: true,
350
+ ignoreInitial: true,
351
+ ignored: regExtExtension,
352
+ });
353
+ // ✨ OPTIMIZACIÓN: Pre-cargar módulos críticos al iniciar el watcher
354
+ watcher.on('ready', async () => {
355
+ const chalkInstance = await loadChalk();
356
+ logger.info(chalkInstance.green(`👀 : Listo para observar \n${fileWatch
357
+ .map((item) => `${item}`)
358
+ .join('\n')}\n`));
359
+ // Pre-cargar módulos críticos para primera compilación más rápida
360
+ setImmediate(async () => {
361
+ try {
362
+ // Pre-cargar módulos básicos que se usarán en compilación
363
+ await Promise.all([
364
+ import('../compiler/compile.js'),
365
+ import('../compiler/parser.js'),
366
+ ]);
367
+ }
368
+ catch {
369
+ // Ignorar errores de pre-carga, no son críticos
370
+ }
371
+ });
372
+ });
373
+ // ✨ CONFIGURAR: Establecer la instancia de browserSync en el debouncer
374
+ watchDebouncer.setBrowserSyncInstance(bs);
375
+ // ✨ OPTIMIZADO: Evento cuando se añade un archivo - Con debouncing
376
+ watcher.on('add', async (ruta) => {
377
+ const isAdditional = isAdditionalWatchFile(ruta, watchAditional);
378
+ const action = getAction(ruta, extendsionWatch.filter((item) => item !== undefined));
379
+ // Usar sistema de debouncing en lugar de compilación inmediata
380
+ watchDebouncer.addChange(ruta, 'add', action, isAdditional);
381
+ });
382
+ // ✨ OPTIMIZADO: Evento cuando se modifica un archivo - Con debouncing
383
+ watcher.on('change', async (ruta) => {
384
+ const isAdditional = isAdditionalWatchFile(ruta, watchAditional);
385
+ const action = getAction(ruta, extendsionWatch.filter((item) => item !== undefined));
386
+ // Usar sistema de debouncing en lugar de compilación inmediata
387
+ watchDebouncer.addChange(ruta, 'change', action, isAdditional);
388
+ });
389
+ // ✨ OPTIMIZADO: Evento cuando se elimina un archivo - Con debouncing
390
+ watcher.on('unlink', async (ruta) => {
391
+ const action = getAction(ruta, extendsionWatch.filter((item) => item !== undefined));
392
+ const isAdditional = isAdditionalWatchFile(ruta, watchAditional);
393
+ // Usar sistema de debouncing para eliminaciones también
394
+ watchDebouncer.addChange(ruta, 'unlink', action, isAdditional);
395
+ });
396
+ return watcher;
397
+ }
398
+ catch (error) {
399
+ logger.error(`🚩 :Error al iniciar watch: ${error instanceof Error ? error.message : String(error)}`);
400
+ if (process.env.NODE_ENV !== 'test') {
401
+ process.exit(1);
402
+ }
403
+ throw error;
404
+ }
405
+ }
406
+ /**
407
+ * ✨ FIX #3: Limpia todos los recursos de watch mode
408
+ * Cierra watchers y limpia timers para evitar fugas de memoria
409
+ */
410
+ export async function cleanupWatcher(watcher) {
411
+ try {
412
+ console.log('[FileWatcher] Limpiando recursos...');
413
+ // 1. Limpiar debouncer
414
+ watchDebouncer.cleanup();
415
+ // 2. Cerrar watcher de chokidar
416
+ if (watcher) {
417
+ await watcher.close();
418
+ }
419
+ console.log('[FileWatcher] Recursos limpiados correctamente');
420
+ }
421
+ catch (error) {
422
+ console.error('[FileWatcher] Error al limpiar recursos:', error instanceof Error ? error.message : String(error));
423
+ }
424
+ }
425
+ //# sourceMappingURL=file-watcher.js.map
@@ -1,3 +1,63 @@
1
- import*as e from"node:process";let t=null;export function setProgressManagerGetter(e){t=e}class r{constructor(){e.stdout.write=e.stdout.write.bind(e.stdout),e.stderr.write=e.stderr.write.bind(e.stderr)}writeMessage(n,r=!1,i=!1){if(t){let e=t();if(e&&e.isActive()){i?e.addImmediateLog(n):e.addLog(n);return}}r?e.stderr.write(n+`
2
- `):e.stdout.write(n+`
3
- `)}log(...e){this.writeMessage(e.map(e=>String(e)).join(` `))}info(...t){let n=e.env.VERBOSE===`true`;this.writeMessage(t.map(e=>String(e)).join(` `),!1,n)}error(...e){this.writeMessage(e.map(e=>String(e)).join(` `),!0)}warn(...e){this.writeMessage(e.map(e=>String(e)).join(` `),!0)}debug(...e){this.writeMessage(e.map(e=>String(e)).join(` `))}fatal(...e){this.writeMessage(e.map(e=>String(e)).join(` `),!0)}table(e,t){let n=t?console.table(e,t):console.table(e);this.writeMessage(String(n))}}export const logger=new r;
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
+ }
7
+ class Logger {
8
+ constructor() {
9
+ // Bind console methods
10
+ process.stdout.write = process.stdout.write.bind(process.stdout);
11
+ process.stderr.write = process.stderr.write.bind(process.stderr);
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
+ }
35
+ log(...args) {
36
+ this.writeMessage(args.map(arg => String(arg)).join(' '));
37
+ }
38
+ info(...args) {
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);
42
+ }
43
+ error(...args) {
44
+ this.writeMessage(args.map(arg => String(arg)).join(' '), true);
45
+ }
46
+ warn(...args) {
47
+ this.writeMessage(args.map(arg => String(arg)).join(' '), true);
48
+ }
49
+ debug(...args) {
50
+ this.writeMessage(args.map(arg => String(arg)).join(' '));
51
+ }
52
+ fatal(...args) {
53
+ this.writeMessage(args.map(arg => String(arg)).join(' '), true);
54
+ }
55
+ table(data, title) {
56
+ const tableString = title
57
+ ? console.table(data, title)
58
+ : console.table(data);
59
+ this.writeMessage(String(tableString));
60
+ }
61
+ }
62
+ export const logger = new Logger();
63
+ //# sourceMappingURL=logger.js.map