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.
- package/README.md +511 -977
- package/dist/wu-framework.cjs.js +3 -1
- package/dist/wu-framework.cjs.js.map +1 -0
- package/dist/wu-framework.dev.js +7533 -2761
- package/dist/wu-framework.dev.js.map +1 -1
- package/dist/wu-framework.esm.js +3 -0
- package/dist/wu-framework.esm.js.map +1 -0
- package/dist/wu-framework.umd.js +3 -1
- package/dist/wu-framework.umd.js.map +1 -0
- package/integrations/astro/README.md +127 -0
- package/integrations/astro/WuApp.astro +63 -0
- package/integrations/astro/WuShell.astro +39 -0
- package/integrations/astro/index.js +68 -0
- package/integrations/astro/package.json +38 -0
- package/integrations/astro/types.d.ts +53 -0
- package/package.json +94 -74
- package/src/adapters/angular/ai.js +30 -0
- package/src/adapters/angular/index.d.ts +154 -0
- package/src/adapters/angular/index.js +932 -0
- package/src/adapters/angular.d.ts +3 -154
- package/src/adapters/angular.js +3 -813
- package/src/adapters/index.js +35 -24
- package/src/adapters/lit/ai.js +20 -0
- package/src/adapters/lit/index.d.ts +120 -0
- package/src/adapters/lit/index.js +721 -0
- package/src/adapters/lit.d.ts +3 -120
- package/src/adapters/lit.js +3 -726
- package/src/adapters/preact/ai.js +33 -0
- package/src/adapters/preact/index.d.ts +108 -0
- package/src/adapters/preact/index.js +661 -0
- package/src/adapters/preact.d.ts +3 -108
- package/src/adapters/preact.js +3 -665
- package/src/adapters/react/ai.js +135 -0
- package/src/adapters/react/index.d.ts +246 -0
- package/src/adapters/react/index.js +689 -0
- package/src/adapters/react.d.ts +3 -212
- package/src/adapters/react.js +3 -513
- package/src/adapters/shared.js +64 -0
- package/src/adapters/solid/ai.js +32 -0
- package/src/adapters/solid/index.d.ts +101 -0
- package/src/adapters/solid/index.js +586 -0
- package/src/adapters/solid.d.ts +3 -101
- package/src/adapters/solid.js +3 -591
- package/src/adapters/svelte/ai.js +31 -0
- package/src/adapters/svelte/index.d.ts +166 -0
- package/src/adapters/svelte/index.js +798 -0
- package/src/adapters/svelte.d.ts +3 -166
- package/src/adapters/svelte.js +3 -803
- package/src/adapters/vanilla/ai.js +30 -0
- package/src/adapters/vanilla/index.d.ts +179 -0
- package/src/adapters/vanilla/index.js +785 -0
- package/src/adapters/vanilla.d.ts +3 -179
- package/src/adapters/vanilla.js +3 -791
- package/src/adapters/vue/ai.js +52 -0
- package/src/adapters/vue/index.d.ts +299 -0
- package/src/adapters/vue/index.js +608 -0
- package/src/adapters/vue.d.ts +3 -299
- package/src/adapters/vue.js +3 -611
- package/src/ai/wu-ai-actions.js +261 -0
- package/src/ai/wu-ai-browser.js +663 -0
- package/src/ai/wu-ai-context.js +332 -0
- package/src/ai/wu-ai-conversation.js +554 -0
- package/src/ai/wu-ai-permissions.js +381 -0
- package/src/ai/wu-ai-provider.js +605 -0
- package/src/ai/wu-ai-schema.js +225 -0
- package/src/ai/wu-ai-triggers.js +396 -0
- package/src/ai/wu-ai.js +474 -0
- package/src/core/wu-app.js +50 -8
- package/src/core/wu-cache.js +1 -1
- package/src/core/wu-core.js +645 -677
- package/src/core/wu-html-parser.js +121 -211
- package/src/core/wu-iframe-sandbox.js +328 -0
- package/src/core/wu-mcp-bridge.js +647 -0
- package/src/core/wu-overrides.js +510 -0
- package/src/core/wu-prefetch.js +414 -0
- package/src/core/wu-proxy-sandbox.js +398 -75
- package/src/core/wu-sandbox.js +86 -268
- package/src/core/wu-script-executor.js +79 -182
- package/src/core/wu-snapshot-sandbox.js +149 -106
- package/src/core/wu-strategies.js +13 -0
- package/src/core/wu-style-bridge.js +0 -2
- package/src/index.js +139 -665
- package/dist/wu-framework.hex.js +0 -23
- package/dist/wu-framework.min.js +0 -1
- package/dist/wu-framework.obf.js +0 -1
- package/scripts/build-protected.js +0 -366
- package/scripts/build.js +0 -212
- package/scripts/rollup-plugin-hex.js +0 -143
- package/src/core/wu-registry.js +0 -60
- 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 };
|
package/src/core/wu-registry.js
DELETED
|
@@ -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
|
-
}
|