versacompiler 2.0.7 → 2.1.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 (40) hide show
  1. package/dist/compiler/compile.js +25 -2332
  2. package/dist/compiler/error-reporter.js +38 -467
  3. package/dist/compiler/linter.js +1 -72
  4. package/dist/compiler/minify.js +1 -229
  5. package/dist/compiler/minifyTemplate.js +1 -0
  6. package/dist/compiler/module-resolution-optimizer.js +1 -821
  7. package/dist/compiler/parser.js +1 -203
  8. package/dist/compiler/performance-monitor.js +56 -192
  9. package/dist/compiler/tailwindcss.js +1 -39
  10. package/dist/compiler/transform-optimizer.js +1 -392
  11. package/dist/compiler/transformTStoJS.js +1 -16
  12. package/dist/compiler/transforms.js +1 -550
  13. package/dist/compiler/typescript-compiler.js +2 -172
  14. package/dist/compiler/typescript-error-parser.js +10 -281
  15. package/dist/compiler/typescript-manager.js +2 -273
  16. package/dist/compiler/typescript-sync-validator.js +31 -295
  17. package/dist/compiler/typescript-worker-pool.js +1 -842
  18. package/dist/compiler/typescript-worker-thread.cjs +22 -466
  19. package/dist/compiler/typescript-worker.js +1 -339
  20. package/dist/compiler/vuejs.js +37 -392
  21. package/dist/hrm/VueHRM.js +1 -353
  22. package/dist/hrm/errorScreen.js +1 -83
  23. package/dist/hrm/getInstanciaVue.js +1 -313
  24. package/dist/hrm/initHRM.js +1 -141
  25. package/dist/main.js +7 -347
  26. package/dist/servicios/browserSync.js +2 -503
  27. package/dist/servicios/file-watcher.js +4 -379
  28. package/dist/servicios/logger.js +3 -63
  29. package/dist/servicios/readConfig.js +53 -430
  30. package/dist/utils/excluded-modules.js +1 -36
  31. package/dist/utils/module-resolver.js +1 -466
  32. package/dist/utils/promptUser.js +2 -48
  33. package/dist/utils/proxyValidator.js +1 -68
  34. package/dist/utils/resolve-bin.js +1 -48
  35. package/dist/utils/utils.js +1 -21
  36. package/dist/utils/vue-types-setup.js +241 -435
  37. package/dist/wrappers/eslint-node.js +3 -1
  38. package/dist/wrappers/oxlint-node.js +1 -120
  39. package/dist/wrappers/tailwind-node.js +1 -92
  40. package/package.json +103 -108
@@ -1,503 +1,2 @@
1
- import { createHash } from 'node:crypto';
2
- import { promises as fs } from 'node:fs';
3
- import path from 'node:path';
4
- import process, { env } from 'node:process';
5
- import browserSync from 'browser-sync';
6
-
7
- import getPort from 'get-port';
8
- import { promptUser } from '../utils/promptUser.js';
9
- import { getProxyInfo, validateProxyAvailability, } from '../utils/proxyValidator.js';
10
- import { logger } from './logger.js';
11
- class BrowserSyncFileCache {
12
- static instance;
13
- cache = new Map();
14
- MAX_CACHE_SIZE = 200; // Máximo archivos en cache
15
- MAX_CACHE_MEMORY = 50 * 1024 * 1024; // 50MB límite
16
- CACHE_TTL = 15 * 60 * 1000; // 15 minutos para archivos estáticos
17
- currentMemoryUsage = 0;
18
- // Métricas
19
- cacheHits = 0;
20
- cacheMisses = 0;
21
- totalRequests = 0;
22
- static getInstance() {
23
- if (!BrowserSyncFileCache.instance) {
24
- BrowserSyncFileCache.instance = new BrowserSyncFileCache();
25
- }
26
- return BrowserSyncFileCache.instance;
27
- }
28
- /**
29
- * Genera ETag para el archivo basado en contenido y timestamp
30
- */
31
- generateETag(filePath, stats) {
32
- const hash = createHash('md5')
33
- .update(`${filePath}:${stats.mtime.getTime()}:${stats.size}`)
34
- .digest('hex');
35
- return `"${hash}"`;
36
- }
37
- /**
38
- * Determina el Content-Type basado en la extensión del archivo
39
- */
40
- getContentType(filePath) {
41
- const ext = path.extname(filePath).toLowerCase();
42
- const mimeTypes = {
43
- '.js': 'application/javascript',
44
- '.mjs': 'application/javascript',
45
- '.ts': 'application/javascript', // Se transpila a JS
46
- '.css': 'text/css',
47
- '.html': 'text/html',
48
- '.json': 'application/json',
49
- '.png': 'image/png',
50
- '.jpg': 'image/jpeg',
51
- '.jpeg': 'image/jpeg',
52
- '.gif': 'image/gif',
53
- '.svg': 'image/svg+xml',
54
- '.ico': 'image/x-icon',
55
- '.webp': 'image/webp',
56
- '.avif': 'image/avif',
57
- '.woff': 'font/woff',
58
- '.woff2': 'font/woff2',
59
- '.ttf': 'font/ttf',
60
- '.eot': 'application/vnd.ms-fontobject',
61
- '.map': 'application/json',
62
- '.xml': 'application/xml',
63
- '.txt': 'text/plain',
64
- '.pdf': 'application/pdf',
65
- '.zip': 'application/zip',
66
- '.mp4': 'video/mp4',
67
- '.mp3': 'audio/mpeg',
68
- '.wav': 'audio/wav',
69
- '.ogg': 'audio/ogg',
70
- };
71
- return mimeTypes[ext] || 'application/octet-stream';
72
- }
73
- /**
74
- * Verifica si el archivo debe ser cacheado
75
- */
76
- shouldCache(filePath) {
77
- const ext = path.extname(filePath).toLowerCase();
78
- const cacheableExtensions = [
79
- '.js',
80
- '.mjs',
81
- '.css',
82
- '.json',
83
- '.png',
84
- '.jpg',
85
- '.jpeg',
86
- '.gif',
87
- '.svg',
88
- '.ico',
89
- '.webp',
90
- '.avif',
91
- '.woff',
92
- '.woff2',
93
- '.ttf',
94
- '.eot',
95
- '.map',
96
- ];
97
- return cacheableExtensions.includes(ext);
98
- }
99
- /**
100
- * Obtiene archivo desde cache o lo lee del disco
101
- */
102
- async getOrReadFile(filePath) {
103
- this.totalRequests++;
104
- try {
105
- // Verificar si el archivo existe y obtener stats
106
- const stats = await fs.stat(filePath);
107
- const lastModified = stats.mtime.getTime();
108
- const etag = this.generateETag(filePath, stats);
109
- // Si no debe ser cacheado, leer directamente
110
- if (!this.shouldCache(filePath)) {
111
- const content = await fs.readFile(filePath, 'utf-8');
112
- return {
113
- content,
114
- contentType: this.getContentType(filePath),
115
- etag,
116
- cached: false,
117
- };
118
- }
119
- // Verificar cache
120
- const cached = this.cache.get(filePath);
121
- if (cached && cached.lastModified === lastModified) {
122
- this.cacheHits++;
123
- return {
124
- content: cached.content,
125
- contentType: cached.contentType,
126
- etag: cached.etag,
127
- cached: true,
128
- };
129
- }
130
- // Cache miss - leer archivo
131
- this.cacheMisses++;
132
- const isBinary = this.isBinaryFile(filePath);
133
- const content = await fs.readFile(filePath, isBinary ? undefined : 'utf-8');
134
- const contentType = this.getContentType(filePath);
135
- // Cachear resultado
136
- this.addToCache(filePath, {
137
- content,
138
- contentType,
139
- lastModified,
140
- etag,
141
- size: stats.size,
142
- });
143
- return {
144
- content,
145
- contentType,
146
- etag,
147
- cached: false,
148
- };
149
- }
150
- catch {
151
- return null;
152
- }
153
- }
154
- /**
155
- * Determina si un archivo es binario
156
- */
157
- isBinaryFile(filePath) {
158
- const ext = path.extname(filePath).toLowerCase();
159
- const binaryExtensions = [
160
- '.png',
161
- '.jpg',
162
- '.jpeg',
163
- '.gif',
164
- '.ico',
165
- '.webp',
166
- '.avif',
167
- '.woff',
168
- '.woff2',
169
- '.ttf',
170
- '.eot',
171
- '.pdf',
172
- '.zip',
173
- '.mp4',
174
- '.mp3',
175
- '.wav',
176
- '.ogg',
177
- ];
178
- return binaryExtensions.includes(ext);
179
- }
180
- /**
181
- * Añade archivo al cache con gestión de memoria
182
- */
183
- addToCache(filePath, fileData) {
184
- try {
185
- // Aplicar políticas de eviction si es necesario
186
- this.evictIfNeeded(fileData.size);
187
- const cacheEntry = {
188
- content: fileData.content,
189
- contentType: fileData.contentType,
190
- lastModified: fileData.lastModified,
191
- etag: fileData.etag,
192
- size: fileData.size,
193
- };
194
- this.cache.set(filePath, cacheEntry);
195
- this.currentMemoryUsage += fileData.size;
196
- }
197
- catch (error) {
198
- console.warn('[BrowserSyncFileCache] Error cacheando archivo:', error);
199
- }
200
- }
201
- /**
202
- * Aplica políticas de eviction LRU si es necesario
203
- */
204
- evictIfNeeded(newFileSize) {
205
- // Verificar límite de archivos
206
- while (this.cache.size >= this.MAX_CACHE_SIZE) {
207
- this.evictOldest();
208
- }
209
- // Verificar límite de memoria
210
- while (this.currentMemoryUsage + newFileSize > this.MAX_CACHE_MEMORY &&
211
- this.cache.size > 0) {
212
- this.evictOldest();
213
- }
214
- }
215
- /**
216
- * Elimina el archivo más antiguo del cache
217
- */
218
- evictOldest() {
219
- let oldestPath = '';
220
- let oldestTime = Infinity;
221
- for (const [filePath, entry] of this.cache) {
222
- if (entry.lastModified < oldestTime) {
223
- oldestTime = entry.lastModified;
224
- oldestPath = filePath;
225
- }
226
- }
227
- if (oldestPath) {
228
- const entry = this.cache.get(oldestPath);
229
- if (entry) {
230
- this.currentMemoryUsage -= entry.size;
231
- this.cache.delete(oldestPath);
232
- }
233
- }
234
- }
235
- /**
236
- * Invalidar cache para un archivo específico
237
- */
238
- invalidateFile(filePath) {
239
- const entry = this.cache.get(filePath);
240
- if (entry) {
241
- this.currentMemoryUsage -= entry.size;
242
- this.cache.delete(filePath);
243
- }
244
- }
245
- /**
246
- * Obtiene estadísticas del cache
247
- */
248
- getStats() {
249
- const hitRate = this.totalRequests > 0
250
- ? Math.round((this.cacheHits / this.totalRequests) * 100)
251
- : 0;
252
- return {
253
- cacheHits: this.cacheHits,
254
- cacheMisses: this.cacheMisses,
255
- hitRate,
256
- totalRequests: this.totalRequests,
257
- cacheSize: this.cache.size,
258
- maxCacheSize: this.MAX_CACHE_SIZE,
259
- memoryUsage: this.currentMemoryUsage,
260
- maxMemoryUsage: this.MAX_CACHE_MEMORY,
261
- };
262
- }
263
- /**
264
- * Limpia todo el cache
265
- */
266
- clear() {
267
- this.cache.clear();
268
- this.currentMemoryUsage = 0;
269
- this.cacheHits = 0;
270
- this.cacheMisses = 0;
271
- this.totalRequests = 0;
272
- }
273
- }
274
- // Instancia global del cache de archivos
275
- const fileCache = BrowserSyncFileCache.getInstance();
276
- // Lazy loading para chalk
277
- const loadChalk = async () => {
278
- const { default: chalk } = await import('chalk');
279
- return chalk;
280
- };
281
- export async function browserSyncServer() {
282
- try {
283
- let bs = null;
284
- const AssetsOmit = env.AssetsOmit === 'true';
285
- let proxy = {
286
- server: './',
287
- };
288
- // ✨ VALIDACIÓN DE PROXY: Verificar disponibilidad antes de inicializar BrowserSync
289
- if (env.proxyUrl) {
290
- logger.info(`🔍 Validando disponibilidad del servidor proxy: ${env.proxyUrl}`);
291
- const isProxyAvailable = await validateProxyAvailability(env.proxyUrl, 5000);
292
- if (!isProxyAvailable) {
293
- const proxyInfo = getProxyInfo(env.proxyUrl);
294
- logger.warn(`⚠️ El servidor proxy no está disponible:`);
295
- logger.warn(` Host: ${proxyInfo.host}`);
296
- logger.warn(` Puerto: ${proxyInfo.port}`);
297
- logger.warn(` Protocolo: ${proxyInfo.protocol}`);
298
- const response = await promptUser('\n¿Desea continuar de todos modos? El modo proxy podría no funcionar correctamente. (s/n): ', 30000);
299
- if (response.toLowerCase().trim() !== 's' &&
300
- response.toLowerCase().trim() !== 'si') {
301
- logger.info('🛑 Operación cancelada por el usuario.');
302
- process.exit(0);
303
- }
304
- logger.warn('⚠️ Continuando con el servidor proxy no disponible...');
305
- }
306
- else {
307
- logger.info('✅ Servidor proxy disponible');
308
- }
309
- proxy = {
310
- proxy: env.proxyUrl,
311
- };
312
- }
313
- const hrmDir = path.join(env.PATH_PROY || process.cwd(), 'hrm');
314
- const projectRoot = process.cwd();
315
- const relativeHrmPath = path.relative(projectRoot, hrmDir);
316
- bs = browserSync.create();
317
- const port = await getPort({ port: 3000 });
318
- const uiPort = await getPort({ port: 4000 });
319
- bs.init({
320
- ...proxy,
321
- files: [`${env.PATH_DIST}/**/*.css`], // Observa cambios en archivos CSS
322
- injectChanges: true, // Inyecta CSS sin recargar la página
323
- open: false, // No abre automáticamente el navegador
324
- port, // Puerto aleatorio para BrowserSync
325
- ui: {
326
- port: uiPort, // Puerto aleatorio para la interfaz de usuario
327
- },
328
- socket: {
329
- path: '/browser-sync/socket.io', // Ruta correcta para socket.io
330
- },
331
- snippetOptions: {
332
- rule: {
333
- match: /<\/body>/i,
334
- fn: (snippet, match) => {
335
- return `
336
- ${snippet}${match}
337
- <script
338
- type="module"
339
- src="/__versa/initHRM.js"></script>
340
- `;
341
- },
342
- },
343
- },
344
- logLevel: 'info',
345
- logPrefix: 'BS',
346
- logConnections: true,
347
- logFileChanges: true,
348
- watchEvents: ['change', 'add', 'unlink', 'addDir', 'unlinkDir'],
349
- reloadDelay: 500,
350
- reloadDebounce: 500,
351
- reloadOnRestart: true,
352
- notify: true,
353
- watchOptions: {
354
- ignoreInitial: true,
355
- ignored: ['node_modules', '.git'],
356
- },
357
- middleware: [
358
- async function (req, res, next) {
359
- //para evitar el error de CORS
360
- res.setHeader('Access-Control-Allow-Origin', '*');
361
- res.setHeader('Access-Control-Allow-Methods', '*');
362
- res.setHeader('Access-Control-Allow-Headers', '*');
363
- res.setHeader('Access-Control-Allow-Credentials', 'true');
364
- res.setHeader('Access-Control-Max-Age', '3600');
365
- res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
366
- res.setHeader('Pragma', 'no-cache');
367
- res.setHeader('Expires', '0');
368
- //para redigir a la ubicación correcta
369
- if (req.url === '/__versa/initHRM.js') {
370
- // ✨ OPTIMIZADO: Usar cache para archivos HRM
371
- const vueLoaderPath = path.join(relativeHrmPath, '/initHRM.js');
372
- const cachedFile = await fileCache.getOrReadFile(vueLoaderPath);
373
- if (cachedFile) {
374
- res.setHeader('Content-Type', cachedFile.contentType);
375
- res.setHeader('ETag', cachedFile.etag);
376
- // if (
377
- // process.env.VERBOSE === 'true' &&
378
- // cachedFile.cached
379
- // ) {
380
- // logger.info(
381
- // `🚀 File cache hit para ${vueLoaderPath}`,
382
- // );
383
- // }
384
- res.end(cachedFile.content);
385
- }
386
- else {
387
- const chalkInstance = await loadChalk();
388
- logger.error(chalkInstance.red(`🚩 :Error al leer el archivo ${vueLoaderPath}`));
389
- res.statusCode = 404;
390
- res.end('// vueLoader.js not found');
391
- }
392
- return;
393
- }
394
- // Si la URL comienza con /__versa/hrm/, sirve los archivos de dist/hrm
395
- if (req.url.startsWith('/__versa/')) {
396
- // ✨ OPTIMIZADO: Usar cache para archivos Versa
397
- const filePath = path.join(relativeHrmPath, req.url.replace('/__versa/', ''));
398
- const cachedFile = await fileCache.getOrReadFile(filePath);
399
- if (cachedFile) {
400
- res.setHeader('Content-Type', cachedFile.contentType);
401
- res.setHeader('ETag', cachedFile.etag);
402
- // if (
403
- // process.env.VERBOSE === 'true' &&
404
- // cachedFile.cached
405
- // ) {
406
- // logger.info(
407
- // `🚀 File cache hit para ${filePath}`,
408
- // );
409
- // }
410
- res.end(cachedFile.content);
411
- }
412
- else {
413
- const chalkInstance = await loadChalk();
414
- logger.error(chalkInstance.red(`🚩 :Error al leer el archivo ${filePath}`));
415
- res.statusCode = 404;
416
- res.end('// Not found');
417
- }
418
- return;
419
- }
420
- // Si la URL comienza con /node_modules/, sirve los archivos de node_modules
421
- if (req.url.startsWith('/node_modules/')) {
422
- // ✨ OPTIMIZADO: Usar cache para módulos de node_modules
423
- const modulePath = path.join(process.cwd(), req.url);
424
- const cachedFile = await fileCache.getOrReadFile(modulePath);
425
- if (cachedFile) {
426
- res.setHeader('Content-Type', cachedFile.contentType);
427
- res.setHeader('ETag', cachedFile.etag);
428
- // if (
429
- // process.env.VERBOSE === 'true' &&
430
- // cachedFile.cached
431
- // ) {
432
- // logger.info(
433
- // `🚀 Module cache hit para ${modulePath}`,
434
- // );
435
- // }
436
- res.end(cachedFile.content);
437
- }
438
- else {
439
- const chalkInstance = await loadChalk();
440
- logger.error(chalkInstance.red(`🚩 Error al leer el módulo ${modulePath}`));
441
- res.statusCode = 404;
442
- res.end('// Module not found');
443
- }
444
- return;
445
- }
446
- // detectar si es un archivo estático, puede que contenga un . y alguna extensión o dashUsers.js?v=1746559083866
447
- const isAssets = req.url.match(/\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot|map|webp|avif|json|html|xml|txt|pdf|zip|mp4|mp3|wav|ogg)(\?.*)?$/i);
448
- if (req.method === 'GET') {
449
- const chalkInstance = await loadChalk();
450
- // omitir archivos estáticos sólo si AssetsOmit es true
451
- if (isAssets && !AssetsOmit) {
452
- logger.info(chalkInstance.white(`GET: ${req.url}`));
453
- }
454
- else if (!isAssets) {
455
- logger.info(chalkInstance.cyan(`GET: ${req.url}`));
456
- }
457
- }
458
- else if (req.method === 'POST') {
459
- const chalkInstance = await loadChalk();
460
- logger.info(chalkInstance.blue(`POST: ${req.url}`));
461
- }
462
- else if (req.method === 'PUT') {
463
- const chalkInstance = await loadChalk();
464
- logger.info(chalkInstance.yellow(`PUT: ${req.url}`));
465
- }
466
- else if (req.method === 'DELETE') {
467
- const chalkInstance = await loadChalk();
468
- logger.info(chalkInstance.red(`DELETE: ${req.url}`));
469
- }
470
- else {
471
- const chalkInstance = await loadChalk();
472
- logger.info(chalkInstance.gray(`${req.method}: ${req.url}`));
473
- }
474
- // Aquí podrías, por ejemplo, escribir estos logs en un archivo o base de datos
475
- next();
476
- },
477
- ],
478
- });
479
- return bs;
480
- }
481
- catch (error) {
482
- logger.error(`🚩 :Error al iniciar BrowserSync: ${error instanceof Error ? error.message : String(error)}`);
483
- process.exit(1);
484
- }
485
- }
486
- export async function emitirCambios(bs, action, filePath) {
487
- const chalkInstance = await loadChalk();
488
- logger.info(chalkInstance.green(`[HMR] Emitiendo cambios: ${action} ${filePath}\n`));
489
- const normalizedPath = path.normalize(filePath).replace(/\\/g, '/');
490
- const nameFile = path.basename(normalizedPath, path.extname(normalizedPath));
491
- bs.sockets.emit(action, { action, filePath, normalizedPath, nameFile });
492
- }
493
- // ✨ NUEVAS FUNCIONES: Exportar funcionalidades del cache de archivos para uso externo
494
- export const getBrowserSyncCacheStats = () => {
495
- return fileCache.getStats();
496
- };
497
- export const clearBrowserSyncCache = () => {
498
- fileCache.clear();
499
- };
500
- export const invalidateBrowserSyncFile = (filePath) => {
501
- fileCache.invalidateFile(filePath);
502
- };
503
- //# sourceMappingURL=browserSync.js.map
1
+ import{createHash as e}from"node:crypto";import{promises as t}from"node:fs";import n from"node:path";import r,{env as i}from"node:process";import a from"browser-sync";import o from"get-port";import{promptUser as s}from"../utils/promptUser.js";import{getProxyInfo as c,validateProxyAvailability as l}from"../utils/proxyValidator.js";import{logger as u}from"./logger.js";class d{static instance;cache=new Map;MAX_CACHE_SIZE=200;MAX_CACHE_MEMORY=50*1024*1024;CACHE_TTL=900*1e3;currentMemoryUsage=0;cleanupInterval=null;cacheHits=0;cacheMisses=0;totalRequests=0;constructor(){this.startAutoCleanup()}static getInstance(){return d.instance||(d.instance=new d),d.instance}startAutoCleanup(){this.cleanupInterval=setInterval(()=>{this.cleanupExpiredEntries()},300*1e3)}cleanupExpiredEntries(){let e=Date.now(),t=0;for(let[n,r]of this.cache.entries())e-r.lastModified>this.CACHE_TTL&&(this.currentMemoryUsage-=r.size,this.cache.delete(n),t++);t>0&&console.log(`[BrowserSync] Limpiadas ${t} entradas expiradas del cache`)}generateETag(t,n){return`"${e(`md5`).update(`${t}:${n.mtime.getTime()}:${n.size}`).digest(`hex`)}"`}getContentType(e){let t=n.extname(e).toLowerCase();return{".js":`application/javascript`,".mjs":`application/javascript`,".ts":`application/javascript`,".css":`text/css`,".html":`text/`,".json":`application/json`,".png":`image/png`,".jpg":`image/jpeg`,".jpeg":`image/jpeg`,".gif":`image/gif`,".svg":`image/svg+xml`,".ico":`image/x-icon`,".webp":`image/webp`,".avif":`image/avif`,".woff":`font/woff`,".woff2":`font/woff2`,".ttf":`font/ttf`,".eot":`application/vnd.ms-fontobject`,".map":`application/json`,".xml":`application/xml`,".txt":`text/plain`,".pdf":`application/pdf`,".zip":`application/zip`,".mp4":`video/mp4`,".mp3":`audio/mpeg`,".wav":`audio/wav`,".ogg":`audio/ogg`}[t]||`application/octet-stream`}shouldCache(e){let t=n.extname(e).toLowerCase();return[`.js`,`.mjs`,`.css`,`.json`,`.png`,`.jpg`,`.jpeg`,`.gif`,`.svg`,`.ico`,`.webp`,`.avif`,`.woff`,`.woff2`,`.ttf`,`.eot`,`.map`].includes(t)}async getOrReadFile(e){this.totalRequests++;try{let n=await t.stat(e),r=n.mtime.getTime(),i=this.generateETag(e,n);if(!this.shouldCache(e))return{content:await t.readFile(e,`utf-8`),contentType:this.getContentType(e),etag:i,cached:!1};let a=this.cache.get(e);if(a&&a.lastModified===r)return this.cacheHits++,{content:a.content,contentType:a.contentType,etag:a.etag,cached:!0};this.cacheMisses++;let o=this.isBinaryFile(e),s=await t.readFile(e,o?void 0:`utf-8`),c=this.getContentType(e);return this.addToCache(e,{content:s,contentType:c,lastModified:r,etag:i,size:n.size}),{content:s,contentType:c,etag:i,cached:!1}}catch{return null}}isBinaryFile(e){let t=n.extname(e).toLowerCase();return[`.png`,`.jpg`,`.jpeg`,`.gif`,`.ico`,`.webp`,`.avif`,`.woff`,`.woff2`,`.ttf`,`.eot`,`.pdf`,`.zip`,`.mp4`,`.mp3`,`.wav`,`.ogg`].includes(t)}addToCache(e,t){try{this.evictIfNeeded(t.size);let n={content:t.content,contentType:t.contentType,lastModified:t.lastModified,etag:t.etag,size:t.size};this.cache.set(e,n),this.currentMemoryUsage+=t.size}catch(e){console.warn(`[BrowserSyncFileCache] Error cacheando archivo:`,e)}}evictIfNeeded(e){for(;this.cache.size>=this.MAX_CACHE_SIZE;)this.evictOldest();for(;this.currentMemoryUsage+e>this.MAX_CACHE_MEMORY&&this.cache.size>0;)this.evictOldest()}evictOldest(){let e=``,t=1/0;for(let[n,r]of this.cache)r.lastModified<t&&(t=r.lastModified,e=n);if(e){let t=this.cache.get(e);t&&(this.currentMemoryUsage-=t.size,this.cache.delete(e))}}invalidateFile(e){let t=this.cache.get(e);t&&(this.currentMemoryUsage-=t.size,this.cache.delete(e))}getStats(){let e=this.totalRequests>0?Math.round(this.cacheHits/this.totalRequests*100):0;return{cacheHits:this.cacheHits,cacheMisses:this.cacheMisses,hitRate:e,totalRequests:this.totalRequests,cacheSize:this.cache.size,maxCacheSize:this.MAX_CACHE_SIZE,memoryUsage:this.currentMemoryUsage,maxMemoryUsage:this.MAX_CACHE_MEMORY}}clear(){this.cache.clear(),this.currentMemoryUsage=0,this.cacheHits=0,this.cacheMisses=0,this.totalRequests=0}terminate(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=null),this.clear()}}const f=d.getInstance(),p=async()=>{let{default:e}=await import(`chalk`);return e};export async function browserSyncServer(){try{let e=null,t=i.AssetsOmit===`true`,d={server:`./`};if(i.proxyUrl){if(u.info(`🔍 Validando disponibilidad del servidor proxy: ${i.proxyUrl}`),await l(i.proxyUrl,5e3))u.info(`✅ Servidor proxy disponible`);else{let e=c(i.proxyUrl);u.warn(`⚠️ El servidor proxy no está disponible:`),u.warn(` Host: ${e.host}`),u.warn(` Puerto: ${e.port}`),u.warn(` Protocolo: ${e.protocol}`);let t=await s(`
2
+ ¿Desea continuar de todos modos? El modo proxy podría no funcionar correctamente. (s/n): `,3e4);t.toLowerCase().trim()!==`s`&&t.toLowerCase().trim()!==`si`&&(u.info(`🛑 Operación cancelada por el usuario.`),r.exit(0)),u.warn(`⚠️ Continuando con el servidor proxy no disponible...`)}d={proxy:i.proxyUrl}}let m=n.join(i.PATH_PROY||r.cwd(),`hrm`),h=r.cwd(),g=n.relative(h,m);e=a.create();let _=await o({port:3e3}),v=await o({port:4e3});return e.init({...d,files:[`${i.PATH_DIST}/**/*.css`],injectChanges:!0,open:!1,port:_,ui:{port:v},socket:{path:`/browser-sync/socket.io`},snippetOptions:{rule:{match:/<\/body>/i,fn:(e,t)=>`${e}${t}<script type="module" src="/__versa/initHRM.js"><\/script>`}},logLevel:`info`,logPrefix:`BS`,logConnections:!0,logFileChanges:!0,watchEvents:[`change`,`add`,`unlink`,`addDir`,`unlinkDir`],reloadDelay:500,reloadDebounce:500,reloadOnRestart:!0,notify:!0,watchOptions:{ignoreInitial:!0,ignored:[`node_modules`,`.git`]},middleware:[async function(e,i,a){if(i.setHeader(`Access-Control-Allow-Origin`,`*`),i.setHeader(`Access-Control-Allow-Methods`,`*`),i.setHeader(`Access-Control-Allow-Headers`,`*`),i.setHeader(`Access-Control-Allow-Credentials`,`true`),i.setHeader(`Access-Control-Max-Age`,`3600`),i.setHeader(`Cache-Control`,`no-cache, no-store, must-revalidate`),i.setHeader(`Pragma`,`no-cache`),i.setHeader(`Expires`,`0`),e.url===`/__versa/initHRM.js`){let e=n.join(g,`/initHRM.js`),t=await f.getOrReadFile(e);if(t)i.setHeader(`Content-Type`,t.contentType),i.setHeader(`ETag`,t.etag),i.end(t.content);else{let t=await p();u.error(t.red(`🚩 :Error al leer el archivo ${e}`)),i.statusCode=404,i.end(`// vueLoader.js not found`)}return}if(e.url.startsWith(`/__versa/`)){let t=n.join(g,e.url.replace(`/__versa/`,``)),r=await f.getOrReadFile(t);if(r)i.setHeader(`Content-Type`,r.contentType),i.setHeader(`ETag`,r.etag),i.end(r.content);else{let e=await p();u.error(e.red(`🚩 :Error al leer el archivo ${t}`)),i.statusCode=404,i.end(`// Not found`)}return}if(e.url.startsWith(`/node_modules/`)){let t=n.join(r.cwd(),e.url),a=await f.getOrReadFile(t);if(a)i.setHeader(`Content-Type`,a.contentType),i.setHeader(`ETag`,a.etag),i.end(a.content);else{let e=await p();u.error(e.red(`🚩 Error al leer el módulo ${t}`)),i.statusCode=404,i.end(`// Module not found`)}return}let o=e.url.match(/\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot|map|webp|avif|json|html|xml|txt|pdf|zip|mp4|mp3|wav|ogg)(\?.*)?$/i);if(e.method===`GET`){let n=await p();o&&!t?u.info(n.white(`GET: ${e.url}`)):o||u.info(n.cyan(`GET: ${e.url}`))}else if(e.method===`POST`){let t=await p();u.info(t.blue(`POST: ${e.url}`))}else if(e.method===`PUT`){let t=await p();u.info(t.yellow(`PUT: ${e.url}`))}else if(e.method===`DELETE`){let t=await p();u.info(t.red(`DELETE: ${e.url}`))}else{let t=await p();u.info(t.gray(`${e.method}: ${e.url}`))}a()}]}),e}catch(e){u.error(`🚩 :Error al iniciar BrowserSync: ${e instanceof Error?e.message:String(e)}`),r.exit(1)}}export async function emitirCambios(e,t,r){let i=await p();u.info(i.green(`[HMR] Emitiendo cambios: ${t} ${r}\n`));let a=n.normalize(r).replace(/\\/g,`/`),o=n.basename(a,n.extname(a));e.sockets.emit(t,{action:t,filePath:r,normalizedPath:a,nameFile:o})}export const getBrowserSyncCacheStats=()=>f.getStats();export const clearBrowserSyncCache=()=>{f.clear()};export const invalidateBrowserSyncFile=e=>{f.invalidateFile(e)};