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
package/src/core/wu-loader.js
CHANGED
|
@@ -1,273 +1,385 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* Carga aplicaciones y componentes sin depender del framework
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* WU-LOADER: SISTEMA DE CARGA DINAMICA UNIVERSAL
|
|
3
|
+
* Carga aplicaciones y componentes sin depender del framework
|
|
4
|
+
*
|
|
5
|
+
* Cache strategy: LRU with TTL eviction.
|
|
6
|
+
* Entries track lastAccess time. When the cache reaches maxCacheSize,
|
|
7
|
+
* the least recently accessed entry is evicted. Entries older than
|
|
8
|
+
* cacheTTL are treated as stale and removed on access or eviction.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { logger } from './wu-logger.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {Object} WuLoaderOptions
|
|
15
|
+
* @property {number} [maxCacheSize=50] - Maximum cache entries
|
|
16
|
+
* @property {number} [cacheTTL=1800000] - Cache TTL in ms (default 30min)
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {Object} WuLoaderStats
|
|
21
|
+
* @property {number} cached - Number of cached entries
|
|
22
|
+
* @property {number} loading - Number of in-flight loads
|
|
23
|
+
* @property {number} maxCacheSize - Max cache size setting
|
|
24
|
+
* @property {number} cacheTTL - Cache TTL setting
|
|
25
|
+
* @property {string[]} cacheKeys - Cached URL keys
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export class WuLoader {
|
|
29
|
+
/**
|
|
30
|
+
* @param {Object} options
|
|
31
|
+
* @param {number} [options.maxCacheSize=50] - Maximum number of entries in the cache
|
|
32
|
+
* @param {number} [options.cacheTTL=1800000] - Time-to-live for cache entries in ms (default 30 minutes)
|
|
33
|
+
*/
|
|
34
|
+
constructor(options = {}) {
|
|
35
|
+
this.maxCacheSize = options.maxCacheSize ?? 50;
|
|
36
|
+
this.cacheTTL = options.cacheTTL ?? 1800000;
|
|
37
|
+
this.cache = new Map();
|
|
38
|
+
this.loadingPromises = new Map();
|
|
39
|
+
|
|
40
|
+
logger.debug('[WuLoader] Dynamic loader initialized');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Read from cache with TTL validation and LRU access tracking.
|
|
45
|
+
* Returns undefined if the entry does not exist or has expired.
|
|
46
|
+
* @param {string} key
|
|
47
|
+
* @returns {string|undefined}
|
|
48
|
+
*/
|
|
49
|
+
_cacheGet(key) {
|
|
50
|
+
if (!this.cache.has(key)) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const entry = this.cache.get(key);
|
|
55
|
+
const now = Date.now();
|
|
56
|
+
|
|
57
|
+
if (now - entry.timestamp > this.cacheTTL) {
|
|
58
|
+
this.cache.delete(key);
|
|
59
|
+
logger.debug(`[WuLoader] Cache expired for: ${key}`);
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Promote: delete and re-insert so iteration order reflects recency.
|
|
64
|
+
// Map iteration order in JS follows insertion order, so the oldest
|
|
65
|
+
// inserted entry is always first -- exactly what we need for LRU eviction.
|
|
66
|
+
this.cache.delete(key);
|
|
67
|
+
entry.lastAccess = now;
|
|
68
|
+
this.cache.set(key, entry);
|
|
69
|
+
|
|
70
|
+
return entry.code;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Write to cache. Evicts stale and LRU entries before inserting.
|
|
75
|
+
* @param {string} key
|
|
76
|
+
* @param {string} code
|
|
77
|
+
*/
|
|
78
|
+
_cacheSet(key, code) {
|
|
79
|
+
// If the key already exists, remove it first so re-insertion
|
|
80
|
+
// moves it to the end (most-recently-used position).
|
|
81
|
+
if (this.cache.has(key)) {
|
|
82
|
+
this.cache.delete(key);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this._evictIfNeeded();
|
|
86
|
+
|
|
87
|
+
const now = Date.now();
|
|
88
|
+
this.cache.set(key, {
|
|
89
|
+
code,
|
|
90
|
+
timestamp: now,
|
|
91
|
+
lastAccess: now
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Evict entries until cache is below maxCacheSize.
|
|
97
|
+
*
|
|
98
|
+
* Two-pass strategy:
|
|
99
|
+
* 1. Remove all expired entries (TTL exceeded).
|
|
100
|
+
* 2. If still at capacity, remove the least recently accessed entry.
|
|
101
|
+
* Because Map preserves insertion order and _cacheGet promotes on
|
|
102
|
+
* access, the first key from the iterator is always the LRU entry.
|
|
103
|
+
*/
|
|
104
|
+
_evictIfNeeded() {
|
|
105
|
+
const now = Date.now();
|
|
106
|
+
|
|
107
|
+
// Pass 1: purge expired entries
|
|
108
|
+
for (const [key, entry] of this.cache) {
|
|
109
|
+
if (now - entry.timestamp > this.cacheTTL) {
|
|
110
|
+
this.cache.delete(key);
|
|
111
|
+
logger.debug(`[WuLoader] Evicted expired entry: ${key}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Pass 2: evict LRU entries until we are under the limit
|
|
116
|
+
while (this.cache.size >= this.maxCacheSize) {
|
|
117
|
+
// Map.keys().next() gives us the oldest-inserted key (LRU)
|
|
118
|
+
const oldestKey = this.cache.keys().next().value;
|
|
119
|
+
this.cache.delete(oldestKey);
|
|
120
|
+
logger.debug(`[WuLoader] Evicted LRU entry: ${oldestKey}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Cargar aplicacion completa
|
|
126
|
+
* @param {string} appUrl - URL base de la aplicacion
|
|
127
|
+
* @param {Object} manifest - Manifest de la aplicacion
|
|
128
|
+
* @returns {string} Codigo JavaScript de la aplicacion
|
|
129
|
+
*/
|
|
130
|
+
async loadApp(appUrl, manifest) {
|
|
131
|
+
const entryFile = manifest?.entry || 'index.js';
|
|
132
|
+
const fullUrl = `${appUrl}/${entryFile}`;
|
|
133
|
+
|
|
134
|
+
logger.debug(`[WuLoader] Loading app from: ${fullUrl}`);
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
// Check cache with TTL and LRU tracking
|
|
138
|
+
const cached = this._cacheGet(fullUrl);
|
|
139
|
+
if (cached !== undefined) {
|
|
140
|
+
logger.debug(`[WuLoader] Cache hit for: ${fullUrl}`);
|
|
141
|
+
return cached;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Check if already loading
|
|
145
|
+
if (this.loadingPromises.has(fullUrl)) {
|
|
146
|
+
logger.debug(`[WuLoader] Loading in progress for: ${fullUrl}`);
|
|
147
|
+
return await this.loadingPromises.get(fullUrl);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Create loading promise
|
|
151
|
+
const loadingPromise = this.fetchCode(fullUrl);
|
|
152
|
+
this.loadingPromises.set(fullUrl, loadingPromise);
|
|
153
|
+
|
|
154
|
+
const code = await loadingPromise;
|
|
155
|
+
|
|
156
|
+
// Clean up loading promise and cache result
|
|
157
|
+
this.loadingPromises.delete(fullUrl);
|
|
158
|
+
this._cacheSet(fullUrl, code);
|
|
159
|
+
|
|
160
|
+
logger.debug(`[WuLoader] App loaded successfully: ${fullUrl}`);
|
|
161
|
+
return code;
|
|
162
|
+
|
|
163
|
+
} catch (error) {
|
|
164
|
+
this.loadingPromises.delete(fullUrl);
|
|
165
|
+
console.error(`[WuLoader] Failed to load app: ${fullUrl}`, error);
|
|
166
|
+
throw new Error(`Failed to load app from ${fullUrl}: ${error.message}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Cargar componente especifico
|
|
172
|
+
* @param {string} appUrl - URL base de la aplicacion
|
|
173
|
+
* @param {string} componentPath - Ruta del componente
|
|
174
|
+
* @returns {Function} Funcion del componente
|
|
175
|
+
*/
|
|
176
|
+
async loadComponent(appUrl, componentPath) {
|
|
177
|
+
// Normalizar ruta del componente
|
|
178
|
+
let normalizedPath = componentPath;
|
|
179
|
+
if (normalizedPath.startsWith('./')) {
|
|
180
|
+
normalizedPath = normalizedPath.substring(2);
|
|
181
|
+
}
|
|
182
|
+
if (!normalizedPath.endsWith('.js') && !normalizedPath.endsWith('.jsx')) {
|
|
183
|
+
normalizedPath += '.js';
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const fullUrl = `${appUrl}/${normalizedPath}`;
|
|
187
|
+
|
|
188
|
+
logger.debug(`[WuLoader] Loading component from: ${fullUrl}`);
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
// Cargar codigo del componente
|
|
192
|
+
const code = await this.loadCode(fullUrl);
|
|
193
|
+
|
|
194
|
+
// Crear funcion que retorna el componente
|
|
195
|
+
const componentFunction = new Function('require', 'module', 'exports', `
|
|
196
|
+
${code}
|
|
197
|
+
return typeof module.exports === 'function' ? module.exports :
|
|
198
|
+
typeof module.exports === 'object' && module.exports.default ? module.exports.default :
|
|
199
|
+
exports.default || exports;
|
|
200
|
+
`);
|
|
201
|
+
|
|
202
|
+
// Ejecutar y obtener el componente
|
|
203
|
+
const fakeModule = { exports: {} };
|
|
204
|
+
const fakeRequire = (name) => {
|
|
205
|
+
logger.warn(`[WuLoader] Component ${componentPath} requires ${name} - not supported yet`);
|
|
206
|
+
return {};
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const component = componentFunction(fakeRequire, fakeModule, fakeModule.exports);
|
|
210
|
+
|
|
211
|
+
logger.debug(`[WuLoader] Component loaded: ${componentPath}`);
|
|
212
|
+
return component;
|
|
213
|
+
|
|
214
|
+
} catch (error) {
|
|
215
|
+
console.error(`[WuLoader] Failed to load component: ${componentPath}`, error);
|
|
216
|
+
throw new Error(`Failed to load component ${componentPath}: ${error.message}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Cargar codigo con cache
|
|
222
|
+
* @param {string} url - URL del archivo
|
|
223
|
+
* @returns {string} Codigo JavaScript
|
|
224
|
+
*/
|
|
225
|
+
async loadCode(url) {
|
|
226
|
+
// Check cache with TTL and LRU tracking
|
|
227
|
+
const cached = this._cacheGet(url);
|
|
228
|
+
if (cached !== undefined) {
|
|
229
|
+
return cached;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Check if already loading
|
|
233
|
+
if (this.loadingPromises.has(url)) {
|
|
234
|
+
return await this.loadingPromises.get(url);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Create loading promise
|
|
238
|
+
const loadingPromise = this.fetchCode(url);
|
|
239
|
+
this.loadingPromises.set(url, loadingPromise);
|
|
240
|
+
|
|
241
|
+
try {
|
|
242
|
+
const code = await loadingPromise;
|
|
243
|
+
this.loadingPromises.delete(url);
|
|
244
|
+
this._cacheSet(url, code);
|
|
245
|
+
return code;
|
|
246
|
+
} catch (error) {
|
|
247
|
+
this.loadingPromises.delete(url);
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Realizar fetch del codigo
|
|
254
|
+
* @param {string} url - URL del archivo
|
|
255
|
+
* @returns {string} Codigo JavaScript
|
|
256
|
+
*/
|
|
257
|
+
async fetchCode(url) {
|
|
258
|
+
const response = await fetch(url, {
|
|
259
|
+
cache: 'no-cache',
|
|
260
|
+
headers: {
|
|
261
|
+
'Accept': 'application/javascript, text/javascript, */*'
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
if (!response.ok) {
|
|
266
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const code = await response.text();
|
|
270
|
+
|
|
271
|
+
if (!code.trim()) {
|
|
272
|
+
throw new Error('Empty response');
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return code;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Precargar aplicaciones
|
|
280
|
+
* @param {Array} appConfigs - Configuraciones de aplicaciones
|
|
281
|
+
*/
|
|
282
|
+
async preload(appConfigs) {
|
|
283
|
+
logger.debug(`[WuLoader] Preloading ${appConfigs.length} apps...`);
|
|
284
|
+
|
|
285
|
+
const preloadPromises = appConfigs.map(async (config) => {
|
|
286
|
+
try {
|
|
287
|
+
await this.loadApp(config.url, config.manifest);
|
|
288
|
+
logger.debug(`[WuLoader] Preloaded: ${config.name}`);
|
|
289
|
+
} catch (error) {
|
|
290
|
+
logger.warn(`[WuLoader] Failed to preload ${config.name}:`, error.message);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
await Promise.allSettled(preloadPromises);
|
|
295
|
+
logger.debug(`[WuLoader] Preload completed`);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Verificar si una URL esta disponible
|
|
300
|
+
* @param {string} url - URL a verificar
|
|
301
|
+
* @returns {boolean} True si esta disponible
|
|
302
|
+
*/
|
|
303
|
+
async isAvailable(url) {
|
|
304
|
+
try {
|
|
305
|
+
const response = await fetch(url, { method: 'HEAD' });
|
|
306
|
+
return response.ok;
|
|
307
|
+
} catch {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Resolver dependencias de imports
|
|
314
|
+
* @param {Array} imports - Lista de imports del manifest
|
|
315
|
+
* @param {Map} availableApps - Apps disponibles
|
|
316
|
+
*/
|
|
317
|
+
async resolveDependencies(imports, availableApps) {
|
|
318
|
+
const resolved = new Map();
|
|
319
|
+
|
|
320
|
+
for (const importPath of imports || []) {
|
|
321
|
+
const [appName, componentName] = importPath.split('.');
|
|
322
|
+
|
|
323
|
+
if (!appName || !componentName) {
|
|
324
|
+
logger.warn(`[WuLoader] Invalid import format: ${importPath}`);
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const app = availableApps.get(appName);
|
|
329
|
+
if (!app) {
|
|
330
|
+
logger.warn(`[WuLoader] Import app not found: ${appName}`);
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const manifest = app.manifest;
|
|
335
|
+
const exportPath = manifest?.wu?.exports?.[componentName];
|
|
336
|
+
|
|
337
|
+
if (!exportPath) {
|
|
338
|
+
logger.warn(`[WuLoader] Export not found: ${importPath}`);
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
try {
|
|
343
|
+
const component = await this.loadComponent(app.url, exportPath);
|
|
344
|
+
resolved.set(importPath, component);
|
|
345
|
+
logger.debug(`[WuLoader] Resolved dependency: ${importPath}`);
|
|
346
|
+
} catch (error) {
|
|
347
|
+
console.error(`[WuLoader] Failed to resolve: ${importPath}`, error);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return resolved;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Limpiar cache
|
|
356
|
+
* @param {string} pattern - Patron opcional para limpiar URLs especificas
|
|
357
|
+
*/
|
|
358
|
+
clearCache(pattern) {
|
|
359
|
+
if (pattern) {
|
|
360
|
+
const regex = new RegExp(pattern);
|
|
361
|
+
for (const [url] of this.cache) {
|
|
362
|
+
if (regex.test(url)) {
|
|
363
|
+
this.cache.delete(url);
|
|
364
|
+
logger.debug(`[WuLoader] Cleared cache for: ${url}`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
} else {
|
|
368
|
+
this.cache.clear();
|
|
369
|
+
logger.debug(`[WuLoader] Cache cleared completely`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Obtener estadisticas del loader
|
|
375
|
+
*/
|
|
376
|
+
getStats() {
|
|
377
|
+
return {
|
|
378
|
+
cached: this.cache.size,
|
|
379
|
+
maxCacheSize: this.maxCacheSize,
|
|
380
|
+
cacheTTL: this.cacheTTL,
|
|
381
|
+
loading: this.loadingPromises.size,
|
|
382
|
+
cacheKeys: Array.from(this.cache.keys())
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
}
|