wu-framework 1.1.6 → 1.1.8

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 (90) hide show
  1. package/README.md +511 -977
  2. package/dist/wu-framework.cjs.js +3 -1
  3. package/dist/wu-framework.cjs.js.map +1 -0
  4. package/dist/wu-framework.dev.js +7533 -2761
  5. package/dist/wu-framework.dev.js.map +1 -1
  6. package/dist/wu-framework.esm.js +3 -0
  7. package/dist/wu-framework.esm.js.map +1 -0
  8. package/dist/wu-framework.umd.js +3 -1
  9. package/dist/wu-framework.umd.js.map +1 -0
  10. package/integrations/astro/README.md +127 -0
  11. package/integrations/astro/WuApp.astro +63 -0
  12. package/integrations/astro/WuShell.astro +39 -0
  13. package/integrations/astro/index.js +68 -0
  14. package/integrations/astro/package.json +38 -0
  15. package/integrations/astro/types.d.ts +53 -0
  16. package/package.json +94 -74
  17. package/src/adapters/angular/ai.js +30 -0
  18. package/src/adapters/angular/index.d.ts +154 -0
  19. package/src/adapters/angular/index.js +932 -0
  20. package/src/adapters/angular.d.ts +3 -154
  21. package/src/adapters/angular.js +3 -813
  22. package/src/adapters/index.js +35 -24
  23. package/src/adapters/lit/ai.js +20 -0
  24. package/src/adapters/lit/index.d.ts +120 -0
  25. package/src/adapters/lit/index.js +721 -0
  26. package/src/adapters/lit.d.ts +3 -120
  27. package/src/adapters/lit.js +3 -726
  28. package/src/adapters/preact/ai.js +33 -0
  29. package/src/adapters/preact/index.d.ts +108 -0
  30. package/src/adapters/preact/index.js +661 -0
  31. package/src/adapters/preact.d.ts +3 -108
  32. package/src/adapters/preact.js +3 -665
  33. package/src/adapters/react/ai.js +135 -0
  34. package/src/adapters/react/index.d.ts +246 -0
  35. package/src/adapters/react/index.js +689 -0
  36. package/src/adapters/react.d.ts +3 -212
  37. package/src/adapters/react.js +3 -513
  38. package/src/adapters/shared.js +64 -0
  39. package/src/adapters/solid/ai.js +32 -0
  40. package/src/adapters/solid/index.d.ts +101 -0
  41. package/src/adapters/solid/index.js +586 -0
  42. package/src/adapters/solid.d.ts +3 -101
  43. package/src/adapters/solid.js +3 -591
  44. package/src/adapters/svelte/ai.js +31 -0
  45. package/src/adapters/svelte/index.d.ts +166 -0
  46. package/src/adapters/svelte/index.js +798 -0
  47. package/src/adapters/svelte.d.ts +3 -166
  48. package/src/adapters/svelte.js +3 -803
  49. package/src/adapters/vanilla/ai.js +30 -0
  50. package/src/adapters/vanilla/index.d.ts +179 -0
  51. package/src/adapters/vanilla/index.js +785 -0
  52. package/src/adapters/vanilla.d.ts +3 -179
  53. package/src/adapters/vanilla.js +3 -791
  54. package/src/adapters/vue/ai.js +52 -0
  55. package/src/adapters/vue/index.d.ts +299 -0
  56. package/src/adapters/vue/index.js +608 -0
  57. package/src/adapters/vue.d.ts +3 -299
  58. package/src/adapters/vue.js +3 -611
  59. package/src/ai/wu-ai-actions.js +261 -0
  60. package/src/ai/wu-ai-browser.js +663 -0
  61. package/src/ai/wu-ai-context.js +332 -0
  62. package/src/ai/wu-ai-conversation.js +554 -0
  63. package/src/ai/wu-ai-permissions.js +381 -0
  64. package/src/ai/wu-ai-provider.js +605 -0
  65. package/src/ai/wu-ai-schema.js +225 -0
  66. package/src/ai/wu-ai-triggers.js +396 -0
  67. package/src/ai/wu-ai.js +474 -0
  68. package/src/core/wu-app.js +50 -8
  69. package/src/core/wu-cache.js +1 -1
  70. package/src/core/wu-core.js +645 -677
  71. package/src/core/wu-html-parser.js +121 -211
  72. package/src/core/wu-iframe-sandbox.js +328 -0
  73. package/src/core/wu-mcp-bridge.js +647 -0
  74. package/src/core/wu-overrides.js +510 -0
  75. package/src/core/wu-prefetch.js +414 -0
  76. package/src/core/wu-proxy-sandbox.js +398 -75
  77. package/src/core/wu-sandbox.js +86 -268
  78. package/src/core/wu-script-executor.js +79 -182
  79. package/src/core/wu-snapshot-sandbox.js +149 -106
  80. package/src/core/wu-strategies.js +13 -0
  81. package/src/core/wu-style-bridge.js +0 -2
  82. package/src/index.js +139 -665
  83. package/dist/wu-framework.hex.js +0 -23
  84. package/dist/wu-framework.min.js +0 -1
  85. package/dist/wu-framework.obf.js +0 -1
  86. package/scripts/build-protected.js +0 -366
  87. package/scripts/build.js +0 -212
  88. package/scripts/rollup-plugin-hex.js +0 -143
  89. package/src/core/wu-registry.js +0 -60
  90. package/src/core/wu-sandbox-pool.js +0 -390
@@ -1,143 +0,0 @@
1
- /**
2
- * 🔐 ROLLUP PLUGIN: HEX ENCODER
3
- *
4
- * Convierte el código JavaScript a formato hexadecimal
5
- * para máxima ofuscación y protección del código fuente.
6
- *
7
- * El código resultante se decodifica y ejecuta en runtime.
8
- */
9
-
10
- /**
11
- * Convierte string a hexadecimal
12
- * @param {string} str - String a convertir
13
- * @returns {string} String en hexadecimal
14
- */
15
- function stringToHex(str) {
16
- let hex = '';
17
- for (let i = 0; i < str.length; i++) {
18
- const charCode = str.charCodeAt(i);
19
- hex += charCode.toString(16).padStart(2, '0');
20
- }
21
- return hex;
22
- }
23
-
24
- /**
25
- * Genera el loader que decodifica y ejecuta el código hex
26
- * @param {string} hexCode - Código en hexadecimal
27
- * @param {boolean} isModule - Si es módulo ES
28
- * @returns {string} Código JavaScript con loader
29
- */
30
- function generateLoader(hexCode, isModule = true) {
31
- // Loader minificado que decodifica hex y ejecuta
32
- const loader = `
33
- (function(){
34
- var h="${hexCode}";
35
- var d=function(x){
36
- for(var s="",i=0;i<x.length;i+=2)
37
- s+=String.fromCharCode(parseInt(x.substr(i,2),16));
38
- return s;
39
- };
40
- var c=d(h);
41
- ${isModule ?
42
- 'var b=new Blob([c],{type:"text/javascript"});var u=URL.createObjectURL(b);import(u).then(function(m){URL.revokeObjectURL(u);Object.assign(window.__wu_exports__=window.__wu_exports__||{},m);});' :
43
- 'var s=document.createElement("script");s.text=c;document.head.appendChild(s);'
44
- }
45
- })();
46
- `.trim().replace(/\s+/g, ' ');
47
-
48
- return loader;
49
- }
50
-
51
- /**
52
- * Genera loader asíncrono para módulos ES
53
- * @param {string} hexCode - Código hexadecimal
54
- * @returns {string} Código con loader async
55
- */
56
- function generateAsyncLoader(hexCode) {
57
- return `/*!
58
- * Wu Framework - Hex Encoded Build
59
- * Decode and execute at runtime
60
- */
61
- const __wu_hex__="${hexCode}";
62
- const __wu_decode__=(h)=>{let s="";for(let i=0;i<h.length;i+=2)s+=String.fromCharCode(parseInt(h.substr(i,2),16));return s;};
63
- const __wu_code__=__wu_decode__(__wu_hex__);
64
- const __wu_blob__=new Blob([__wu_code__],{type:"text/javascript"});
65
- const __wu_url__=URL.createObjectURL(__wu_blob__);
66
- const __wu_module__=await import(__wu_url__);
67
- URL.revokeObjectURL(__wu_url__);
68
- export const WuCore=__wu_module__.WuCore;
69
- export const WuLoader=__wu_module__.WuLoader;
70
- export const WuSandbox=__wu_module__.WuSandbox;
71
- export const WuManifest=__wu_module__.WuManifest;
72
- export const WuEventBus=__wu_module__.WuEventBus;
73
- export const WuStore=__wu_module__.WuStore;
74
- export const WuCache=__wu_module__.WuCache;
75
- export const WuPlugin=__wu_module__.WuPlugin;
76
- export const WuHooks=__wu_module__.WuHooks;
77
- export const WuPerformance=__wu_module__.WuPerformance;
78
- export const adapters=__wu_module__.adapters;
79
- export default __wu_module__.default||__wu_module__.WuCore;
80
- `;
81
- }
82
-
83
- /**
84
- * Plugin de Rollup para codificación hexadecimal
85
- * @param {Object} options - Opciones del plugin
86
- * @returns {Object} Plugin de Rollup
87
- */
88
- export default function hexEncoder(options = {}) {
89
- const {
90
- encodeStrings = true,
91
- encodeIdentifiers = true,
92
- addLoader = true,
93
- asyncLoader = true,
94
- chunkSize = 0 // 0 = sin chunks, >0 = dividir en chunks
95
- } = options;
96
-
97
- return {
98
- name: 'hex-encoder',
99
-
100
- renderChunk(code, chunk, outputOptions) {
101
- console.log(`[HexEncoder] Processing chunk: ${chunk.fileName}`);
102
-
103
- // Convertir código a hexadecimal
104
- const hexCode = stringToHex(code);
105
-
106
- console.log(`[HexEncoder] Original size: ${code.length} bytes`);
107
- console.log(`[HexEncoder] Hex size: ${hexCode.length} bytes`);
108
-
109
- if (!addLoader) {
110
- // Solo devolver el hex sin loader
111
- return {
112
- code: `// Wu Framework - Hex Encoded\n// Decode with: hexToString("${hexCode}")\nexport default "${hexCode}";`,
113
- map: null
114
- };
115
- }
116
-
117
- // Generar código con loader
118
- let finalCode;
119
-
120
- if (asyncLoader) {
121
- finalCode = generateAsyncLoader(hexCode);
122
- } else {
123
- finalCode = generateLoader(hexCode, outputOptions.format === 'es');
124
- }
125
-
126
- console.log(`[HexEncoder] Final size: ${finalCode.length} bytes`);
127
-
128
- return {
129
- code: finalCode,
130
- map: null
131
- };
132
- },
133
-
134
- generateBundle(outputOptions, bundle) {
135
- console.log(`[HexEncoder] Build complete!`);
136
- console.log(`[HexEncoder] Output format: ${outputOptions.format}`);
137
- console.log(`[HexEncoder] Files generated: ${Object.keys(bundle).join(', ')}`);
138
- }
139
- };
140
- }
141
-
142
- // Exportar utilidades para uso standalone
143
- export { stringToHex, generateLoader, generateAsyncLoader };
@@ -1,60 +0,0 @@
1
- /**
2
- * 🔔 WU-REGISTRY: APP REGISTRATION TRACKER
3
- * Simplificado - solo trackea apps registradas
4
- */
5
-
6
- export class WuRegistry {
7
- constructor() {
8
- this.registeredApps = new Set();
9
- this._setupNotifyReady();
10
- }
11
-
12
- /**
13
- * 🔔 Setup notifyReady API en window.wu
14
- */
15
- _setupNotifyReady() {
16
- const setupFn = () => {
17
- if (window.wu && !window.wu.notifyReady) {
18
- window.wu.notifyReady = (appName) => {
19
- const event = new CustomEvent('wu:app:ready', {
20
- detail: { appName, timestamp: Date.now() }
21
- });
22
- window.dispatchEvent(event);
23
- };
24
- }
25
- };
26
-
27
- setupFn();
28
- if (!window.wu) {
29
- queueMicrotask(setupFn);
30
- }
31
- }
32
-
33
- /**
34
- * ✅ MARK AS REGISTERED
35
- */
36
- markAsRegistered(appName) {
37
- this.registeredApps.add(appName);
38
- }
39
-
40
- /**
41
- * ❓ IS REGISTERED
42
- */
43
- isRegistered(appName) {
44
- return this.registeredApps.has(appName);
45
- }
46
-
47
- /**
48
- * ❌ UNREGISTER APP
49
- */
50
- unregister(appName) {
51
- this.registeredApps.delete(appName);
52
- }
53
-
54
- /**
55
- * 🧹 CLEANUP
56
- */
57
- cleanup() {
58
- this.registeredApps.clear();
59
- }
60
- }
@@ -1,390 +0,0 @@
1
- /**
2
- * 🏊 WU-SANDBOX-POOL: VIRTUAL SANDBOX POOL
3
- *
4
- * Object Pool pattern para reutilizar sandboxes:
5
- * - Reduce memory usage
6
- * - Reduce GC pressure
7
- * - Mejora performance de mount/unmount
8
- * - Auto-cleanup de sandboxes inactivos
9
- */
10
-
11
- export class WuSandboxPool {
12
- constructor(core) {
13
- this.core = core;
14
-
15
- // Pool configuration
16
- this.config = {
17
- minSize: 2, // Mínimo de sandboxes en pool
18
- maxSize: 10, // Máximo de sandboxes en pool
19
- idleTimeout: 30000, // Tiempo antes de limpiar sandbox (30s)
20
- warmupOnInit: true // Crear sandboxes al inicializar
21
- };
22
-
23
- // Pool state
24
- this.available = []; // Sandboxes disponibles
25
- this.inUse = new Map(); // Sandboxes en uso: appName -> sandbox
26
- this.totalCreated = 0;
27
- this.totalReused = 0;
28
-
29
- // Cleanup timer
30
- this.cleanupTimer = null;
31
-
32
- console.log('[WuSandboxPool] 🏊 Sandbox pool initialized');
33
- }
34
-
35
- /**
36
- * 🚀 INIT: Inicializar pool
37
- */
38
- async init() {
39
- if (this.config.warmupOnInit) {
40
- await this.warmup();
41
- }
42
-
43
- // Iniciar cleanup periódico
44
- this.startCleanupTimer();
45
-
46
- console.log('[WuSandboxPool] Pool ready');
47
- }
48
-
49
- /**
50
- * 🔥 WARMUP: Pre-crear sandboxes
51
- */
52
- async warmup() {
53
- console.log(`[WuSandboxPool] Warming up pool with ${this.config.minSize} sandboxes`);
54
-
55
- for (let i = 0; i < this.config.minSize; i++) {
56
- const sandbox = this.createSandbox();
57
- this.available.push(sandbox);
58
- }
59
-
60
- console.log(`[WuSandboxPool] ✅ Pool warmed up with ${this.available.length} sandboxes`);
61
- }
62
-
63
- /**
64
- * 🎯 CREATE SANDBOX: Crear nuevo sandbox
65
- * @returns {Object} Sandbox instance
66
- */
67
- createSandbox() {
68
- // Crear container temporal
69
- const container = document.createElement('div');
70
- container.className = 'wu-sandbox-container';
71
- container.style.display = 'none';
72
-
73
- // Crear shadow root
74
- const shadowRoot = container.attachShadow({ mode: 'open' });
75
-
76
- // Crear mount point dentro del shadow
77
- const mountPoint = document.createElement('div');
78
- mountPoint.className = 'wu-mount-point';
79
- shadowRoot.appendChild(mountPoint);
80
-
81
- const sandbox = {
82
- id: `sandbox_${this.totalCreated++}`,
83
- container,
84
- shadowRoot,
85
- mountPoint,
86
- createdAt: Date.now(),
87
- lastUsed: Date.now(),
88
- timesUsed: 0,
89
- currentApp: null
90
- };
91
-
92
- console.log(`[WuSandboxPool] Created sandbox: ${sandbox.id}`);
93
-
94
- return sandbox;
95
- }
96
-
97
- /**
98
- * 🔓 ACQUIRE: Obtener sandbox del pool
99
- * @param {string} appName - Nombre de la app
100
- * @returns {Object} Sandbox instance
101
- */
102
- acquire(appName) {
103
- // Verificar si ya tiene un sandbox
104
- if (this.inUse.has(appName)) {
105
- console.warn(`[WuSandboxPool] App "${appName}" already has a sandbox`);
106
- return this.inUse.get(appName);
107
- }
108
-
109
- let sandbox;
110
-
111
- // Intentar reutilizar sandbox disponible
112
- if (this.available.length > 0) {
113
- sandbox = this.available.pop();
114
- this.totalReused++;
115
-
116
- console.log(`[WuSandboxPool] ♻️ Reusing sandbox ${sandbox.id} for ${appName}`);
117
- }
118
- // Si no hay disponibles y no excedemos máximo, crear nuevo
119
- else if (this.inUse.size < this.config.maxSize) {
120
- sandbox = this.createSandbox();
121
-
122
- console.log(`[WuSandboxPool] 🆕 Creating new sandbox ${sandbox.id} for ${appName}`);
123
- }
124
- // Si excedemos máximo, crear temporal (no pooleable)
125
- else {
126
- sandbox = this.createSandbox();
127
- sandbox.temporary = true;
128
-
129
- console.warn(`[WuSandboxPool] ⚠️ Pool exhausted, creating temporary sandbox for ${appName}`);
130
- }
131
-
132
- // Preparar sandbox para uso
133
- this.prepareSandbox(sandbox, appName);
134
-
135
- // Marcar como en uso
136
- sandbox.currentApp = appName;
137
- sandbox.lastUsed = Date.now();
138
- sandbox.timesUsed++;
139
-
140
- this.inUse.set(appName, sandbox);
141
-
142
- return sandbox;
143
- }
144
-
145
- /**
146
- * 🔒 RELEASE: Liberar sandbox al pool
147
- * @param {string} appName - Nombre de la app
148
- */
149
- release(appName) {
150
- const sandbox = this.inUse.get(appName);
151
-
152
- if (!sandbox) {
153
- console.warn(`[WuSandboxPool] App "${appName}" has no sandbox to release`);
154
- return;
155
- }
156
-
157
- // Limpiar sandbox
158
- this.cleanSandbox(sandbox);
159
-
160
- // Remover de uso
161
- this.inUse.delete(appName);
162
- sandbox.currentApp = null;
163
- sandbox.lastUsed = Date.now();
164
-
165
- // Si es temporal, destruir
166
- if (sandbox.temporary) {
167
- this.destroySandbox(sandbox);
168
- console.log(`[WuSandboxPool] 🗑️ Destroyed temporary sandbox ${sandbox.id}`);
169
- return;
170
- }
171
-
172
- // Si pool no está lleno, devolver al pool
173
- if (this.available.length < this.config.maxSize) {
174
- this.available.push(sandbox);
175
- console.log(`[WuSandboxPool] ✅ Released sandbox ${sandbox.id} back to pool`);
176
- }
177
- // Si pool está lleno, destruir
178
- else {
179
- this.destroySandbox(sandbox);
180
- console.log(`[WuSandboxPool] 🗑️ Pool full, destroyed sandbox ${sandbox.id}`);
181
- }
182
- }
183
-
184
- /**
185
- * 🔧 PREPARE SANDBOX: Preparar sandbox para uso
186
- * @param {Object} sandbox - Sandbox instance
187
- * @param {string} appName - Nombre de la app
188
- */
189
- prepareSandbox(sandbox, appName) {
190
- // Mostrar container
191
- sandbox.container.style.display = 'block';
192
-
193
- // Agregar identificador de app
194
- sandbox.container.setAttribute('data-wu-app', appName);
195
-
196
- console.log(`[WuSandboxPool] Prepared sandbox ${sandbox.id} for ${appName}`);
197
- }
198
-
199
- /**
200
- * 🧹 CLEAN SANDBOX: Limpiar sandbox para reutilización
201
- * @param {Object} sandbox - Sandbox instance
202
- */
203
- cleanSandbox(sandbox) {
204
- // Limpiar contenido del mount point
205
- if (sandbox.mountPoint) {
206
- sandbox.mountPoint.innerHTML = '';
207
- }
208
-
209
- // Limpiar estilos del shadow root
210
- if (sandbox.shadowRoot) {
211
- const styles = sandbox.shadowRoot.querySelectorAll('style');
212
- styles.forEach(style => style.remove());
213
- }
214
-
215
- // Ocultar container
216
- sandbox.container.style.display = 'none';
217
-
218
- // Remover identificador de app
219
- sandbox.container.removeAttribute('data-wu-app');
220
-
221
- console.log(`[WuSandboxPool] Cleaned sandbox ${sandbox.id}`);
222
- }
223
-
224
- /**
225
- * 💥 DESTROY SANDBOX: Destruir sandbox completamente
226
- * @param {Object} sandbox - Sandbox instance
227
- */
228
- destroySandbox(sandbox) {
229
- // Limpiar contenido
230
- this.cleanSandbox(sandbox);
231
-
232
- // Remover del DOM si está adjuntado
233
- if (sandbox.container.parentNode) {
234
- sandbox.container.parentNode.removeChild(sandbox.container);
235
- }
236
-
237
- // Limpiar referencias
238
- sandbox.shadowRoot = null;
239
- sandbox.mountPoint = null;
240
- sandbox.container = null;
241
-
242
- console.log(`[WuSandboxPool] Destroyed sandbox ${sandbox.id}`);
243
- }
244
-
245
- /**
246
- * ⏰ START CLEANUP TIMER: Iniciar limpieza periódica
247
- */
248
- startCleanupTimer() {
249
- // Limpiar timer anterior si existe
250
- if (this.cleanupTimer) {
251
- clearInterval(this.cleanupTimer);
252
- }
253
-
254
- // Limpiar cada minuto
255
- this.cleanupTimer = setInterval(() => {
256
- this.cleanupIdleSandboxes();
257
- }, 60000);
258
- }
259
-
260
- /**
261
- * 🧹 CLEANUP IDLE SANDBOXES: Limpiar sandboxes inactivos
262
- */
263
- cleanupIdleSandboxes() {
264
- const now = Date.now();
265
- const threshold = now - this.config.idleTimeout;
266
-
267
- // Filtrar sandboxes que no han sido usados recientemente
268
- const toKeep = [];
269
- const toDestroy = [];
270
-
271
- this.available.forEach(sandbox => {
272
- if (sandbox.lastUsed < threshold && this.available.length > this.config.minSize) {
273
- toDestroy.push(sandbox);
274
- } else {
275
- toKeep.push(sandbox);
276
- }
277
- });
278
-
279
- // Destruir sandboxes idle
280
- toDestroy.forEach(sandbox => {
281
- this.destroySandbox(sandbox);
282
- });
283
-
284
- this.available = toKeep;
285
-
286
- if (toDestroy.length > 0) {
287
- console.log(`[WuSandboxPool] 🧹 Cleaned up ${toDestroy.length} idle sandboxes`);
288
- }
289
-
290
- // Si quedamos por debajo del mínimo, crear nuevos
291
- if (this.available.length < this.config.minSize) {
292
- const needed = this.config.minSize - this.available.length;
293
- console.log(`[WuSandboxPool] Creating ${needed} sandboxes to maintain minimum`);
294
-
295
- for (let i = 0; i < needed; i++) {
296
- this.available.push(this.createSandbox());
297
- }
298
- }
299
- }
300
-
301
- /**
302
- * ⚙️ CONFIGURE: Configurar pool
303
- * @param {Object} config - Nueva configuración
304
- */
305
- configure(config) {
306
- const oldMinSize = this.config.minSize;
307
-
308
- this.config = {
309
- ...this.config,
310
- ...config
311
- };
312
-
313
- // Si aumentó el minSize, crear más sandboxes
314
- if (this.config.minSize > oldMinSize) {
315
- const needed = this.config.minSize - this.available.length;
316
- if (needed > 0) {
317
- console.log(`[WuSandboxPool] Creating ${needed} sandboxes for new minSize`);
318
- for (let i = 0; i < needed; i++) {
319
- this.available.push(this.createSandbox());
320
- }
321
- }
322
- }
323
-
324
- // Si disminuyó el minSize o maxSize, limpiar exceso
325
- if (this.available.length > this.config.maxSize) {
326
- const excess = this.available.length - this.config.maxSize;
327
- const toDestroy = this.available.splice(this.config.maxSize, excess);
328
- toDestroy.forEach(sandbox => this.destroySandbox(sandbox));
329
-
330
- console.log(`[WuSandboxPool] Destroyed ${excess} excess sandboxes`);
331
- }
332
-
333
- console.log('[WuSandboxPool] Configuration updated:', this.config);
334
- }
335
-
336
- /**
337
- * 📊 GET STATS: Estadísticas del pool
338
- * @returns {Object}
339
- */
340
- getStats() {
341
- const totalSandboxes = this.available.length + this.inUse.size;
342
- const utilization = totalSandboxes > 0
343
- ? ((this.inUse.size / totalSandboxes) * 100).toFixed(1)
344
- : 0;
345
-
346
- const avgTimesUsed = totalSandboxes > 0
347
- ? [...this.available, ...this.inUse.values()]
348
- .reduce((sum, s) => sum + s.timesUsed, 0) / totalSandboxes
349
- : 0;
350
-
351
- return {
352
- available: this.available.length,
353
- inUse: this.inUse.size,
354
- totalSandboxes,
355
- utilization: `${utilization}%`,
356
- totalCreated: this.totalCreated,
357
- totalReused: this.totalReused,
358
- reuseRate: this.totalCreated > 0
359
- ? `${((this.totalReused / this.totalCreated) * 100).toFixed(1)}%`
360
- : '0%',
361
- avgTimesUsed: avgTimesUsed.toFixed(1),
362
- config: this.config,
363
- appsInUse: Array.from(this.inUse.keys())
364
- };
365
- }
366
-
367
- /**
368
- * 🧹 CLEANUP: Limpiar todo el pool
369
- */
370
- cleanup() {
371
- // Detener cleanup timer
372
- if (this.cleanupTimer) {
373
- clearInterval(this.cleanupTimer);
374
- this.cleanupTimer = null;
375
- }
376
-
377
- // Destruir todos los sandboxes disponibles
378
- this.available.forEach(sandbox => this.destroySandbox(sandbox));
379
- this.available = [];
380
-
381
- // Destruir sandboxes en uso (forzado)
382
- this.inUse.forEach((sandbox, appName) => {
383
- console.warn(`[WuSandboxPool] Force destroying sandbox for active app: ${appName}`);
384
- this.destroySandbox(sandbox);
385
- });
386
- this.inUse.clear();
387
-
388
- console.log('[WuSandboxPool] 🧹 Pool cleaned up');
389
- }
390
- }