versacompiler 2.0.0 → 2.0.1

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.
@@ -1,4 +1,191 @@
1
+ import { createHash } from 'node:crypto';
1
2
  import { minify } from 'oxc-minify';
3
+ class MinificationCache {
4
+ static instance;
5
+ cache = new Map();
6
+ MAX_CACHE_SIZE = 100; // Máximo archivos minificados en cache
7
+ MAX_CACHE_MEMORY = 20 * 1024 * 1024; // 20MB límite
8
+ CACHE_TTL = 30 * 60 * 1000; // 30 minutos
9
+ currentMemoryUsage = 0;
10
+ // Métricas
11
+ cacheHits = 0;
12
+ cacheMisses = 0;
13
+ totalMinifications = 0;
14
+ totalOriginalSize = 0;
15
+ totalMinifiedSize = 0;
16
+ static getInstance() {
17
+ if (!MinificationCache.instance) {
18
+ MinificationCache.instance = new MinificationCache();
19
+ }
20
+ return MinificationCache.instance;
21
+ }
22
+ /**
23
+ * Genera un hash del contenido y opciones de minificación
24
+ */
25
+ generateCacheKey(data, options) {
26
+ const content = `${data}||${JSON.stringify(options)}`;
27
+ return createHash('sha256').update(content).digest('hex');
28
+ }
29
+ /**
30
+ * Obtiene resultado de minificación desde cache o lo genera
31
+ */
32
+ async getOrMinify(data, filename, options) {
33
+ this.totalMinifications++;
34
+ const cacheKey = this.generateCacheKey(data, options);
35
+ // Verificar cache
36
+ const cached = this.cache.get(cacheKey);
37
+ if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
38
+ // Actualizar timestamp de uso (LRU)
39
+ cached.timestamp = Date.now();
40
+ this.cacheHits++;
41
+ return {
42
+ code: cached.minifiedCode,
43
+ error: null,
44
+ cached: true,
45
+ };
46
+ }
47
+ // Cache miss - minificar código
48
+ this.cacheMisses++;
49
+ const originalSize = data.length;
50
+ try {
51
+ const result = await minify(filename, data, options);
52
+ // Si el código de entrada no estaba vacío pero el resultado sí,
53
+ // probablemente hay un error de sintaxis
54
+ if (data.trim() && !result.code.trim()) {
55
+ const error = new Error(`Minification failed: likely syntax error in ${filename}`);
56
+ return { code: '', error, cached: false };
57
+ }
58
+ const minifiedSize = result.code.length;
59
+ // Cachear resultado exitoso
60
+ this.addToCache(cacheKey, {
61
+ contentHash: cacheKey,
62
+ options,
63
+ minifiedCode: result.code,
64
+ timestamp: Date.now(),
65
+ originalSize,
66
+ minifiedSize,
67
+ });
68
+ // Actualizar métricas globales
69
+ this.totalOriginalSize += originalSize;
70
+ this.totalMinifiedSize += minifiedSize;
71
+ return {
72
+ code: result.code,
73
+ error: null,
74
+ cached: false,
75
+ };
76
+ }
77
+ catch (error) {
78
+ return {
79
+ error: error instanceof Error ? error : new Error(String(error)),
80
+ code: '',
81
+ cached: false,
82
+ };
83
+ }
84
+ }
85
+ /**
86
+ * Añade resultado al cache con gestión de memoria
87
+ */
88
+ addToCache(cacheKey, entry) {
89
+ try {
90
+ const entrySize = entry.originalSize + entry.minifiedSize;
91
+ // Aplicar políticas de eviction si es necesario
92
+ this.evictIfNeeded(entrySize);
93
+ this.cache.set(cacheKey, entry);
94
+ this.currentMemoryUsage += entrySize;
95
+ }
96
+ catch (error) {
97
+ console.warn('[MinificationCache] Error cacheando minificación:', error);
98
+ }
99
+ }
100
+ /**
101
+ * Aplica políticas de eviction LRU si es necesario
102
+ */
103
+ evictIfNeeded(newEntrySize) {
104
+ // Verificar límite de entradas
105
+ while (this.cache.size >= this.MAX_CACHE_SIZE) {
106
+ this.evictLRU();
107
+ }
108
+ // Verificar límite de memoria
109
+ while (this.currentMemoryUsage + newEntrySize > this.MAX_CACHE_MEMORY &&
110
+ this.cache.size > 0) {
111
+ this.evictLRU();
112
+ }
113
+ }
114
+ /**
115
+ * Elimina la entrada menos recientemente usada
116
+ */
117
+ evictLRU() {
118
+ let oldestKey = '';
119
+ let oldestTime = Infinity;
120
+ for (const [key, entry] of this.cache) {
121
+ if (entry.timestamp < oldestTime) {
122
+ oldestTime = entry.timestamp;
123
+ oldestKey = key;
124
+ }
125
+ }
126
+ if (oldestKey) {
127
+ const entry = this.cache.get(oldestKey);
128
+ if (entry) {
129
+ this.currentMemoryUsage -=
130
+ entry.originalSize + entry.minifiedSize;
131
+ this.cache.delete(oldestKey);
132
+ }
133
+ }
134
+ }
135
+ /**
136
+ * Limpia entradas expiradas
137
+ */
138
+ cleanExpired() {
139
+ const now = Date.now();
140
+ for (const [key, entry] of this.cache.entries()) {
141
+ if (now - entry.timestamp > this.CACHE_TTL) {
142
+ this.currentMemoryUsage -=
143
+ entry.originalSize + entry.minifiedSize;
144
+ this.cache.delete(key);
145
+ }
146
+ }
147
+ }
148
+ /**
149
+ * Obtiene estadísticas del cache
150
+ */
151
+ getStats() {
152
+ const hitRate = this.totalMinifications > 0
153
+ ? Math.round((this.cacheHits / this.totalMinifications) * 100)
154
+ : 0;
155
+ const avgCompressionRatio = this.totalOriginalSize > 0
156
+ ? Math.round(((this.totalOriginalSize - this.totalMinifiedSize) /
157
+ this.totalOriginalSize) *
158
+ 100)
159
+ : 0;
160
+ return {
161
+ cacheHits: this.cacheHits,
162
+ cacheMisses: this.cacheMisses,
163
+ hitRate,
164
+ totalMinifications: this.totalMinifications,
165
+ cacheSize: this.cache.size,
166
+ maxCacheSize: this.MAX_CACHE_SIZE,
167
+ memoryUsage: this.currentMemoryUsage,
168
+ maxMemoryUsage: this.MAX_CACHE_MEMORY,
169
+ totalOriginalSize: this.totalOriginalSize,
170
+ totalMinifiedSize: this.totalMinifiedSize,
171
+ avgCompressionRatio,
172
+ };
173
+ }
174
+ /**
175
+ * Limpia todo el cache
176
+ */
177
+ clear() {
178
+ this.cache.clear();
179
+ this.currentMemoryUsage = 0;
180
+ this.cacheHits = 0;
181
+ this.cacheMisses = 0;
182
+ this.totalMinifications = 0;
183
+ this.totalOriginalSize = 0;
184
+ this.totalMinifiedSize = 0;
185
+ }
186
+ }
187
+ // Instancia global del cache de minificación
188
+ const minificationCache = MinificationCache.getInstance();
2
189
  /**
3
190
  * Minifica el codigo JavaScript usando opciones especificas.
4
191
  *
@@ -22,19 +209,21 @@ export const minifyJS = async (data, filename, isProd = true) => {
22
209
  },
23
210
  sourcemap: !isProd,
24
211
  };
25
- const result = await minify(filename, data, options);
26
- // Si el código de entrada no estaba vacío pero el resultado sí,
27
- // probablemente hay un error de sintaxis
28
- if (data.trim() && !result.code.trim()) {
29
- return {
30
- error: new Error(`Minification failed: likely syntax error in ${filename}`),
31
- code: '',
32
- };
33
- }
34
- return { code: result.code, error: null };
212
+ const result = await minificationCache.getOrMinify(data, filename, options);
213
+ return { code: result.code, error: result.error };
35
214
  }
36
215
  catch (error) {
37
216
  return { error, code: '' };
38
217
  }
39
218
  };
219
+ // ✨ NUEVAS FUNCIONES: Exportar funcionalidades del cache de minificación para uso externo
220
+ export const getMinificationCacheStats = () => {
221
+ return minificationCache.getStats();
222
+ };
223
+ export const clearMinificationCache = () => {
224
+ minificationCache.clear();
225
+ };
226
+ export const cleanExpiredMinificationCache = () => {
227
+ minificationCache.cleanExpired();
228
+ };
40
229
  //# sourceMappingURL=minify.js.map