wu-framework 1.1.15 → 1.1.17
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 +52 -20
- package/dist/wu-framework.cjs.js +1 -1
- package/dist/wu-framework.cjs.js.map +1 -1
- package/dist/wu-framework.dev.js +15511 -15146
- package/dist/wu-framework.dev.js.map +1 -1
- package/dist/wu-framework.esm.js +1 -1
- package/dist/wu-framework.esm.js.map +1 -1
- package/dist/wu-framework.umd.js +1 -1
- package/dist/wu-framework.umd.js.map +1 -1
- package/package.json +166 -161
- package/src/adapters/angular/ai.js +30 -30
- package/src/adapters/angular/index.d.ts +154 -154
- package/src/adapters/angular/index.js +932 -932
- package/src/adapters/angular.d.ts +3 -3
- package/src/adapters/angular.js +3 -3
- package/src/adapters/index.js +168 -168
- package/src/adapters/lit/ai.js +20 -20
- package/src/adapters/lit/index.d.ts +120 -120
- package/src/adapters/lit/index.js +721 -721
- package/src/adapters/lit.d.ts +3 -3
- package/src/adapters/lit.js +3 -3
- package/src/adapters/preact/ai.js +33 -33
- package/src/adapters/preact/index.d.ts +108 -108
- package/src/adapters/preact/index.js +661 -661
- package/src/adapters/preact.d.ts +3 -3
- package/src/adapters/preact.js +3 -3
- package/src/adapters/react/index.js +48 -54
- package/src/adapters/react.d.ts +3 -3
- package/src/adapters/react.js +3 -3
- package/src/adapters/shared.js +64 -64
- package/src/adapters/solid/ai.js +32 -32
- package/src/adapters/solid/index.d.ts +101 -101
- package/src/adapters/solid/index.js +586 -586
- package/src/adapters/solid.d.ts +3 -3
- package/src/adapters/solid.js +3 -3
- package/src/adapters/svelte/ai.js +31 -31
- package/src/adapters/svelte/index.d.ts +166 -166
- package/src/adapters/svelte/index.js +798 -798
- package/src/adapters/svelte.d.ts +3 -3
- package/src/adapters/svelte.js +3 -3
- package/src/adapters/vanilla/ai.js +30 -30
- package/src/adapters/vanilla/index.d.ts +179 -179
- package/src/adapters/vanilla/index.js +785 -785
- package/src/adapters/vanilla.d.ts +3 -3
- package/src/adapters/vanilla.js +3 -3
- package/src/adapters/vue/ai.js +52 -52
- package/src/adapters/vue/index.d.ts +299 -299
- package/src/adapters/vue/index.js +610 -610
- package/src/adapters/vue.d.ts +3 -3
- package/src/adapters/vue.js +3 -3
- package/src/ai/wu-ai-actions.js +261 -261
- package/src/ai/wu-ai-agent.js +546 -546
- package/src/ai/wu-ai-browser-primitives.js +354 -354
- package/src/ai/wu-ai-browser.js +380 -380
- package/src/ai/wu-ai-context.js +332 -332
- package/src/ai/wu-ai-conversation.js +613 -613
- package/src/ai/wu-ai-orchestrate.js +1021 -1021
- package/src/ai/wu-ai-permissions.js +381 -381
- package/src/ai/wu-ai-provider.js +700 -700
- package/src/ai/wu-ai-schema.js +225 -225
- package/src/ai/wu-ai-triggers.js +396 -396
- package/src/ai/wu-ai.js +804 -804
- package/src/core/wu-app.js +236 -236
- package/src/core/wu-cache.js +498 -477
- package/src/core/wu-core.js +1412 -1398
- package/src/core/wu-error-boundary.js +396 -382
- package/src/core/wu-event-bus.js +390 -348
- package/src/core/wu-hooks.js +350 -350
- package/src/core/wu-html-parser.js +199 -190
- package/src/core/wu-iframe-sandbox.js +328 -328
- package/src/core/wu-loader.js +385 -273
- package/src/core/wu-logger.js +142 -134
- package/src/core/wu-manifest.js +532 -509
- package/src/core/wu-mcp-bridge.js +432 -432
- package/src/core/wu-overrides.js +510 -510
- package/src/core/wu-performance.js +228 -228
- package/src/core/wu-plugin.js +401 -348
- package/src/core/wu-prefetch.js +414 -414
- package/src/core/wu-proxy-sandbox.js +477 -476
- package/src/core/wu-sandbox.js +779 -779
- package/src/core/wu-script-executor.js +161 -113
- package/src/core/wu-snapshot-sandbox.js +227 -227
- package/src/core/wu-store.js +13 -3
- package/src/core/wu-strategies.js +256 -256
- package/src/core/wu-style-bridge.js +477 -477
- package/src/index.d.ts +317 -0
- package/src/index.js +234 -224
- package/src/utils/dependency-resolver.js +327 -327
|
@@ -1,256 +1,256 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 🎯 WU-STRATEGIES: LOADING STRATEGIES
|
|
3
|
-
*
|
|
4
|
-
* Estrategias de carga para optimizar performance:
|
|
5
|
-
* - Lazy: Carga solo cuando se monta
|
|
6
|
-
* - Eager: Precarga en init
|
|
7
|
-
* - Preload: Usa <link rel="prefetch">
|
|
8
|
-
* - Idle: Carga cuando el navegador está idle
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { logger } from './wu-logger.js';
|
|
12
|
-
|
|
13
|
-
export class WuLoadingStrategy {
|
|
14
|
-
constructor(core) {
|
|
15
|
-
this.core = core;
|
|
16
|
-
this.strategies = new Map();
|
|
17
|
-
this.loadingQueue = [];
|
|
18
|
-
this.isIdle = false;
|
|
19
|
-
|
|
20
|
-
this.registerDefaultStrategies();
|
|
21
|
-
this.setupIdleCallback();
|
|
22
|
-
|
|
23
|
-
logger.debug('[WuStrategies] 🎯 Loading strategies initialized');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 📋 REGISTER DEFAULT STRATEGIES
|
|
28
|
-
*/
|
|
29
|
-
registerDefaultStrategies() {
|
|
30
|
-
// Lazy: Solo carga cuando se necesita (no precarga)
|
|
31
|
-
this.register('lazy', {
|
|
32
|
-
shouldPreload: false,
|
|
33
|
-
load: async (appName, config) => {
|
|
34
|
-
logger.debug(`[Strategy:Lazy] Loading ${appName} on demand (no preload)`);
|
|
35
|
-
// No hace nada, la app se carga cuando se monta
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// Eager: Carga inmediatamente en init
|
|
41
|
-
this.register('eager', {
|
|
42
|
-
shouldPreload: true,
|
|
43
|
-
priority: 'high',
|
|
44
|
-
load: async (appName, config) => {
|
|
45
|
-
logger.debug(`[Strategy:Eager] Preloading ${appName} immediately`);
|
|
46
|
-
|
|
47
|
-
// Cargar el módulo de la app
|
|
48
|
-
const app = this.core.apps.get(appName);
|
|
49
|
-
if (app) {
|
|
50
|
-
const moduleUrl = await this.core.resolveModulePath(app);
|
|
51
|
-
await import(/* @vite-ignore */ moduleUrl);
|
|
52
|
-
logger.debug(`[Strategy:Eager] ✅ ${appName} preloaded`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// Preload: Usa resource hints del navegador
|
|
58
|
-
this.register('preload', {
|
|
59
|
-
shouldPreload: true,
|
|
60
|
-
priority: 'medium',
|
|
61
|
-
load: async (appName, config) => {
|
|
62
|
-
logger.debug(`[Strategy:Preload] Using resource hints for ${appName}`);
|
|
63
|
-
|
|
64
|
-
// Crear <link rel="prefetch">
|
|
65
|
-
const app = this.core.apps.get(appName);
|
|
66
|
-
if (app) {
|
|
67
|
-
const moduleUrl = await this.core.resolveModulePath(app);
|
|
68
|
-
|
|
69
|
-
const link = document.createElement('link');
|
|
70
|
-
link.rel = 'prefetch';
|
|
71
|
-
link.href = moduleUrl;
|
|
72
|
-
link.as = 'script';
|
|
73
|
-
document.head.appendChild(link);
|
|
74
|
-
|
|
75
|
-
logger.debug(`[Strategy:Preload] ✅ Resource hint added for ${appName}`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
// Speculate: Uses Speculation Rules API (Chrome 121+) with fallbacks
|
|
81
|
-
this.register('speculate', {
|
|
82
|
-
shouldPreload: true,
|
|
83
|
-
priority: 'medium',
|
|
84
|
-
load: async (appName, config) => {
|
|
85
|
-
if (this.core.prefetcher) {
|
|
86
|
-
await this.core.prefetcher.prefetch(appName, {
|
|
87
|
-
eagerness: config.eagerness || 'moderate'
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Idle: Carga cuando el navegador está idle
|
|
94
|
-
this.register('idle', {
|
|
95
|
-
shouldPreload: false,
|
|
96
|
-
load: async (appName, config) => {
|
|
97
|
-
logger.debug(`[Strategy:Idle] Queueing ${appName} for idle loading`);
|
|
98
|
-
|
|
99
|
-
return new Promise((resolve) => {
|
|
100
|
-
this.loadingQueue.push({
|
|
101
|
-
appName,
|
|
102
|
-
config,
|
|
103
|
-
resolve
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// Si ya estamos idle, procesar inmediatamente
|
|
107
|
-
if (this.isIdle) {
|
|
108
|
-
this.processIdleQueue();
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* 📦 REGISTER: Registrar estrategia personalizada
|
|
117
|
-
* @param {string} name - Nombre de la estrategia
|
|
118
|
-
* @param {Object} strategy - Configuración de la estrategia
|
|
119
|
-
*/
|
|
120
|
-
register(name, strategy) {
|
|
121
|
-
if (!strategy.load || typeof strategy.load !== 'function') {
|
|
122
|
-
throw new Error('[WuStrategies] Strategy must have a load function');
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
this.strategies.set(name, {
|
|
126
|
-
name,
|
|
127
|
-
shouldPreload: strategy.shouldPreload || false,
|
|
128
|
-
priority: strategy.priority || 'low',
|
|
129
|
-
load: strategy.load
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
logger.debug(`[WuStrategies] Strategy "${name}" registered`);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* 🚀 LOAD: Cargar app con estrategia
|
|
137
|
-
* @param {string} appName - Nombre de la app
|
|
138
|
-
* @param {Object} config - Configuración con strategy
|
|
139
|
-
* @returns {Promise}
|
|
140
|
-
*/
|
|
141
|
-
async load(appName, config) {
|
|
142
|
-
const strategyName = config.strategy || 'lazy';
|
|
143
|
-
const strategy = this.strategies.get(strategyName);
|
|
144
|
-
|
|
145
|
-
if (!strategy) {
|
|
146
|
-
logger.warn(`[WuStrategies] Strategy "${strategyName}" not found, using lazy`);
|
|
147
|
-
return await this.strategies.get('lazy').load(appName, config);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return await strategy.load(appName, config);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* 🎯 PRELOAD: Precargar apps según estrategia
|
|
155
|
-
* @param {Array} apps - Apps a evaluar para precarga
|
|
156
|
-
*/
|
|
157
|
-
async preload(apps) {
|
|
158
|
-
const toPreload = apps.filter(app => {
|
|
159
|
-
const strategy = this.strategies.get(app.strategy || 'lazy');
|
|
160
|
-
return strategy.shouldPreload;
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
// Ordenar por prioridad
|
|
164
|
-
toPreload.sort((a, b) => {
|
|
165
|
-
const priorityOrder = { high: 0, medium: 1, low: 2 };
|
|
166
|
-
const aPriority = this.strategies.get(a.strategy)?.priority || 'low';
|
|
167
|
-
const bPriority = this.strategies.get(b.strategy)?.priority || 'low';
|
|
168
|
-
return priorityOrder[aPriority] - priorityOrder[bPriority];
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
logger.debug(`[WuStrategies] Preloading ${toPreload.length} apps`);
|
|
172
|
-
|
|
173
|
-
// Precargar en orden
|
|
174
|
-
for (const app of toPreload) {
|
|
175
|
-
try {
|
|
176
|
-
await this.load(app.name, app);
|
|
177
|
-
} catch (error) {
|
|
178
|
-
console.error(`[WuStrategies] Failed to preload ${app.name}:`, error);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* ⏰ SETUP IDLE CALLBACK: Configurar idle loading
|
|
185
|
-
*/
|
|
186
|
-
setupIdleCallback() {
|
|
187
|
-
if ('requestIdleCallback' in window) {
|
|
188
|
-
const idleCallback = (deadline) => {
|
|
189
|
-
this.isIdle = true;
|
|
190
|
-
this.processIdleQueue(deadline);
|
|
191
|
-
|
|
192
|
-
// Re-schedule
|
|
193
|
-
requestIdleCallback(idleCallback);
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
requestIdleCallback(idleCallback);
|
|
197
|
-
} else {
|
|
198
|
-
// Fallback: usar setTimeout
|
|
199
|
-
setTimeout(() => {
|
|
200
|
-
this.isIdle = true;
|
|
201
|
-
this.processIdleQueue();
|
|
202
|
-
}, 2000);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* 📋 PROCESS IDLE QUEUE: Procesar cola de carga idle
|
|
208
|
-
* @param {Object} deadline - IdleDeadline object
|
|
209
|
-
*/
|
|
210
|
-
async processIdleQueue(deadline) {
|
|
211
|
-
while (this.loadingQueue.length > 0) {
|
|
212
|
-
// Si tenemos deadline y se acabó el tiempo, salir
|
|
213
|
-
if (deadline && deadline.timeRemaining() <= 0) {
|
|
214
|
-
break;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const item = this.loadingQueue.shift();
|
|
218
|
-
|
|
219
|
-
try {
|
|
220
|
-
const app = this.core.apps.get(item.appName);
|
|
221
|
-
if (app) {
|
|
222
|
-
const moduleUrl = await this.core.resolveModulePath(app);
|
|
223
|
-
await import(/* @vite-ignore */ moduleUrl);
|
|
224
|
-
logger.debug(`[Strategy:Idle] ✅ ${item.appName} loaded during idle time`);
|
|
225
|
-
item.resolve(true);
|
|
226
|
-
} else {
|
|
227
|
-
item.resolve(null);
|
|
228
|
-
}
|
|
229
|
-
} catch (error) {
|
|
230
|
-
console.error(`[Strategy:Idle] Failed to load ${item.appName}:`, error);
|
|
231
|
-
item.resolve(null);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* 📊 GET STATS: Estadísticas de estrategias
|
|
238
|
-
* @returns {Object}
|
|
239
|
-
*/
|
|
240
|
-
getStats() {
|
|
241
|
-
return {
|
|
242
|
-
totalStrategies: this.strategies.size,
|
|
243
|
-
strategies: Array.from(this.strategies.keys()),
|
|
244
|
-
idleQueueSize: this.loadingQueue.length,
|
|
245
|
-
isIdle: this.isIdle
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* 🧹 CLEANUP: Limpiar estrategias
|
|
251
|
-
*/
|
|
252
|
-
cleanup() {
|
|
253
|
-
this.loadingQueue = [];
|
|
254
|
-
logger.debug('[WuStrategies] 🧹 Strategies cleaned up');
|
|
255
|
-
}
|
|
256
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 🎯 WU-STRATEGIES: LOADING STRATEGIES
|
|
3
|
+
*
|
|
4
|
+
* Estrategias de carga para optimizar performance:
|
|
5
|
+
* - Lazy: Carga solo cuando se monta
|
|
6
|
+
* - Eager: Precarga en init
|
|
7
|
+
* - Preload: Usa <link rel="prefetch">
|
|
8
|
+
* - Idle: Carga cuando el navegador está idle
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { logger } from './wu-logger.js';
|
|
12
|
+
|
|
13
|
+
export class WuLoadingStrategy {
|
|
14
|
+
constructor(core) {
|
|
15
|
+
this.core = core;
|
|
16
|
+
this.strategies = new Map();
|
|
17
|
+
this.loadingQueue = [];
|
|
18
|
+
this.isIdle = false;
|
|
19
|
+
|
|
20
|
+
this.registerDefaultStrategies();
|
|
21
|
+
this.setupIdleCallback();
|
|
22
|
+
|
|
23
|
+
logger.debug('[WuStrategies] 🎯 Loading strategies initialized');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 📋 REGISTER DEFAULT STRATEGIES
|
|
28
|
+
*/
|
|
29
|
+
registerDefaultStrategies() {
|
|
30
|
+
// Lazy: Solo carga cuando se necesita (no precarga)
|
|
31
|
+
this.register('lazy', {
|
|
32
|
+
shouldPreload: false,
|
|
33
|
+
load: async (appName, config) => {
|
|
34
|
+
logger.debug(`[Strategy:Lazy] Loading ${appName} on demand (no preload)`);
|
|
35
|
+
// No hace nada, la app se carga cuando se monta
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Eager: Carga inmediatamente en init
|
|
41
|
+
this.register('eager', {
|
|
42
|
+
shouldPreload: true,
|
|
43
|
+
priority: 'high',
|
|
44
|
+
load: async (appName, config) => {
|
|
45
|
+
logger.debug(`[Strategy:Eager] Preloading ${appName} immediately`);
|
|
46
|
+
|
|
47
|
+
// Cargar el módulo de la app
|
|
48
|
+
const app = this.core.apps.get(appName);
|
|
49
|
+
if (app) {
|
|
50
|
+
const moduleUrl = await this.core.resolveModulePath(app);
|
|
51
|
+
await import(/* @vite-ignore */ moduleUrl);
|
|
52
|
+
logger.debug(`[Strategy:Eager] ✅ ${appName} preloaded`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Preload: Usa resource hints del navegador
|
|
58
|
+
this.register('preload', {
|
|
59
|
+
shouldPreload: true,
|
|
60
|
+
priority: 'medium',
|
|
61
|
+
load: async (appName, config) => {
|
|
62
|
+
logger.debug(`[Strategy:Preload] Using resource hints for ${appName}`);
|
|
63
|
+
|
|
64
|
+
// Crear <link rel="prefetch">
|
|
65
|
+
const app = this.core.apps.get(appName);
|
|
66
|
+
if (app) {
|
|
67
|
+
const moduleUrl = await this.core.resolveModulePath(app);
|
|
68
|
+
|
|
69
|
+
const link = document.createElement('link');
|
|
70
|
+
link.rel = 'prefetch';
|
|
71
|
+
link.href = moduleUrl;
|
|
72
|
+
link.as = 'script';
|
|
73
|
+
document.head.appendChild(link);
|
|
74
|
+
|
|
75
|
+
logger.debug(`[Strategy:Preload] ✅ Resource hint added for ${appName}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Speculate: Uses Speculation Rules API (Chrome 121+) with fallbacks
|
|
81
|
+
this.register('speculate', {
|
|
82
|
+
shouldPreload: true,
|
|
83
|
+
priority: 'medium',
|
|
84
|
+
load: async (appName, config) => {
|
|
85
|
+
if (this.core.prefetcher) {
|
|
86
|
+
await this.core.prefetcher.prefetch(appName, {
|
|
87
|
+
eagerness: config.eagerness || 'moderate'
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Idle: Carga cuando el navegador está idle
|
|
94
|
+
this.register('idle', {
|
|
95
|
+
shouldPreload: false,
|
|
96
|
+
load: async (appName, config) => {
|
|
97
|
+
logger.debug(`[Strategy:Idle] Queueing ${appName} for idle loading`);
|
|
98
|
+
|
|
99
|
+
return new Promise((resolve) => {
|
|
100
|
+
this.loadingQueue.push({
|
|
101
|
+
appName,
|
|
102
|
+
config,
|
|
103
|
+
resolve
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Si ya estamos idle, procesar inmediatamente
|
|
107
|
+
if (this.isIdle) {
|
|
108
|
+
this.processIdleQueue();
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 📦 REGISTER: Registrar estrategia personalizada
|
|
117
|
+
* @param {string} name - Nombre de la estrategia
|
|
118
|
+
* @param {Object} strategy - Configuración de la estrategia
|
|
119
|
+
*/
|
|
120
|
+
register(name, strategy) {
|
|
121
|
+
if (!strategy.load || typeof strategy.load !== 'function') {
|
|
122
|
+
throw new Error('[WuStrategies] Strategy must have a load function');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
this.strategies.set(name, {
|
|
126
|
+
name,
|
|
127
|
+
shouldPreload: strategy.shouldPreload || false,
|
|
128
|
+
priority: strategy.priority || 'low',
|
|
129
|
+
load: strategy.load
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
logger.debug(`[WuStrategies] Strategy "${name}" registered`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* 🚀 LOAD: Cargar app con estrategia
|
|
137
|
+
* @param {string} appName - Nombre de la app
|
|
138
|
+
* @param {Object} config - Configuración con strategy
|
|
139
|
+
* @returns {Promise}
|
|
140
|
+
*/
|
|
141
|
+
async load(appName, config) {
|
|
142
|
+
const strategyName = config.strategy || 'lazy';
|
|
143
|
+
const strategy = this.strategies.get(strategyName);
|
|
144
|
+
|
|
145
|
+
if (!strategy) {
|
|
146
|
+
logger.warn(`[WuStrategies] Strategy "${strategyName}" not found, using lazy`);
|
|
147
|
+
return await this.strategies.get('lazy').load(appName, config);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return await strategy.load(appName, config);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 🎯 PRELOAD: Precargar apps según estrategia
|
|
155
|
+
* @param {Array} apps - Apps a evaluar para precarga
|
|
156
|
+
*/
|
|
157
|
+
async preload(apps) {
|
|
158
|
+
const toPreload = apps.filter(app => {
|
|
159
|
+
const strategy = this.strategies.get(app.strategy || 'lazy');
|
|
160
|
+
return strategy.shouldPreload;
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Ordenar por prioridad
|
|
164
|
+
toPreload.sort((a, b) => {
|
|
165
|
+
const priorityOrder = { high: 0, medium: 1, low: 2 };
|
|
166
|
+
const aPriority = this.strategies.get(a.strategy)?.priority || 'low';
|
|
167
|
+
const bPriority = this.strategies.get(b.strategy)?.priority || 'low';
|
|
168
|
+
return priorityOrder[aPriority] - priorityOrder[bPriority];
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
logger.debug(`[WuStrategies] Preloading ${toPreload.length} apps`);
|
|
172
|
+
|
|
173
|
+
// Precargar en orden
|
|
174
|
+
for (const app of toPreload) {
|
|
175
|
+
try {
|
|
176
|
+
await this.load(app.name, app);
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.error(`[WuStrategies] Failed to preload ${app.name}:`, error);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* ⏰ SETUP IDLE CALLBACK: Configurar idle loading
|
|
185
|
+
*/
|
|
186
|
+
setupIdleCallback() {
|
|
187
|
+
if ('requestIdleCallback' in window) {
|
|
188
|
+
const idleCallback = (deadline) => {
|
|
189
|
+
this.isIdle = true;
|
|
190
|
+
this.processIdleQueue(deadline);
|
|
191
|
+
|
|
192
|
+
// Re-schedule
|
|
193
|
+
requestIdleCallback(idleCallback);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
requestIdleCallback(idleCallback);
|
|
197
|
+
} else {
|
|
198
|
+
// Fallback: usar setTimeout
|
|
199
|
+
setTimeout(() => {
|
|
200
|
+
this.isIdle = true;
|
|
201
|
+
this.processIdleQueue();
|
|
202
|
+
}, 2000);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* 📋 PROCESS IDLE QUEUE: Procesar cola de carga idle
|
|
208
|
+
* @param {Object} deadline - IdleDeadline object
|
|
209
|
+
*/
|
|
210
|
+
async processIdleQueue(deadline) {
|
|
211
|
+
while (this.loadingQueue.length > 0) {
|
|
212
|
+
// Si tenemos deadline y se acabó el tiempo, salir
|
|
213
|
+
if (deadline && deadline.timeRemaining() <= 0) {
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const item = this.loadingQueue.shift();
|
|
218
|
+
|
|
219
|
+
try {
|
|
220
|
+
const app = this.core.apps.get(item.appName);
|
|
221
|
+
if (app) {
|
|
222
|
+
const moduleUrl = await this.core.resolveModulePath(app);
|
|
223
|
+
await import(/* @vite-ignore */ moduleUrl);
|
|
224
|
+
logger.debug(`[Strategy:Idle] ✅ ${item.appName} loaded during idle time`);
|
|
225
|
+
item.resolve(true);
|
|
226
|
+
} else {
|
|
227
|
+
item.resolve(null);
|
|
228
|
+
}
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.error(`[Strategy:Idle] Failed to load ${item.appName}:`, error);
|
|
231
|
+
item.resolve(null);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* 📊 GET STATS: Estadísticas de estrategias
|
|
238
|
+
* @returns {Object}
|
|
239
|
+
*/
|
|
240
|
+
getStats() {
|
|
241
|
+
return {
|
|
242
|
+
totalStrategies: this.strategies.size,
|
|
243
|
+
strategies: Array.from(this.strategies.keys()),
|
|
244
|
+
idleQueueSize: this.loadingQueue.length,
|
|
245
|
+
isIdle: this.isIdle
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* 🧹 CLEANUP: Limpiar estrategias
|
|
251
|
+
*/
|
|
252
|
+
cleanup() {
|
|
253
|
+
this.loadingQueue = [];
|
|
254
|
+
logger.debug('[WuStrategies] 🧹 Strategies cleaned up');
|
|
255
|
+
}
|
|
256
|
+
}
|