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.
Files changed (88) hide show
  1. package/README.md +52 -20
  2. package/dist/wu-framework.cjs.js +1 -1
  3. package/dist/wu-framework.cjs.js.map +1 -1
  4. package/dist/wu-framework.dev.js +15511 -15146
  5. package/dist/wu-framework.dev.js.map +1 -1
  6. package/dist/wu-framework.esm.js +1 -1
  7. package/dist/wu-framework.esm.js.map +1 -1
  8. package/dist/wu-framework.umd.js +1 -1
  9. package/dist/wu-framework.umd.js.map +1 -1
  10. package/package.json +166 -161
  11. package/src/adapters/angular/ai.js +30 -30
  12. package/src/adapters/angular/index.d.ts +154 -154
  13. package/src/adapters/angular/index.js +932 -932
  14. package/src/adapters/angular.d.ts +3 -3
  15. package/src/adapters/angular.js +3 -3
  16. package/src/adapters/index.js +168 -168
  17. package/src/adapters/lit/ai.js +20 -20
  18. package/src/adapters/lit/index.d.ts +120 -120
  19. package/src/adapters/lit/index.js +721 -721
  20. package/src/adapters/lit.d.ts +3 -3
  21. package/src/adapters/lit.js +3 -3
  22. package/src/adapters/preact/ai.js +33 -33
  23. package/src/adapters/preact/index.d.ts +108 -108
  24. package/src/adapters/preact/index.js +661 -661
  25. package/src/adapters/preact.d.ts +3 -3
  26. package/src/adapters/preact.js +3 -3
  27. package/src/adapters/react/index.js +48 -54
  28. package/src/adapters/react.d.ts +3 -3
  29. package/src/adapters/react.js +3 -3
  30. package/src/adapters/shared.js +64 -64
  31. package/src/adapters/solid/ai.js +32 -32
  32. package/src/adapters/solid/index.d.ts +101 -101
  33. package/src/adapters/solid/index.js +586 -586
  34. package/src/adapters/solid.d.ts +3 -3
  35. package/src/adapters/solid.js +3 -3
  36. package/src/adapters/svelte/ai.js +31 -31
  37. package/src/adapters/svelte/index.d.ts +166 -166
  38. package/src/adapters/svelte/index.js +798 -798
  39. package/src/adapters/svelte.d.ts +3 -3
  40. package/src/adapters/svelte.js +3 -3
  41. package/src/adapters/vanilla/ai.js +30 -30
  42. package/src/adapters/vanilla/index.d.ts +179 -179
  43. package/src/adapters/vanilla/index.js +785 -785
  44. package/src/adapters/vanilla.d.ts +3 -3
  45. package/src/adapters/vanilla.js +3 -3
  46. package/src/adapters/vue/ai.js +52 -52
  47. package/src/adapters/vue/index.d.ts +299 -299
  48. package/src/adapters/vue/index.js +610 -610
  49. package/src/adapters/vue.d.ts +3 -3
  50. package/src/adapters/vue.js +3 -3
  51. package/src/ai/wu-ai-actions.js +261 -261
  52. package/src/ai/wu-ai-agent.js +546 -546
  53. package/src/ai/wu-ai-browser-primitives.js +354 -354
  54. package/src/ai/wu-ai-browser.js +380 -380
  55. package/src/ai/wu-ai-context.js +332 -332
  56. package/src/ai/wu-ai-conversation.js +613 -613
  57. package/src/ai/wu-ai-orchestrate.js +1021 -1021
  58. package/src/ai/wu-ai-permissions.js +381 -381
  59. package/src/ai/wu-ai-provider.js +700 -700
  60. package/src/ai/wu-ai-schema.js +225 -225
  61. package/src/ai/wu-ai-triggers.js +396 -396
  62. package/src/ai/wu-ai.js +804 -804
  63. package/src/core/wu-app.js +236 -236
  64. package/src/core/wu-cache.js +498 -477
  65. package/src/core/wu-core.js +1412 -1398
  66. package/src/core/wu-error-boundary.js +396 -382
  67. package/src/core/wu-event-bus.js +390 -348
  68. package/src/core/wu-hooks.js +350 -350
  69. package/src/core/wu-html-parser.js +199 -190
  70. package/src/core/wu-iframe-sandbox.js +328 -328
  71. package/src/core/wu-loader.js +385 -273
  72. package/src/core/wu-logger.js +142 -134
  73. package/src/core/wu-manifest.js +532 -509
  74. package/src/core/wu-mcp-bridge.js +432 -432
  75. package/src/core/wu-overrides.js +510 -510
  76. package/src/core/wu-performance.js +228 -228
  77. package/src/core/wu-plugin.js +401 -348
  78. package/src/core/wu-prefetch.js +414 -414
  79. package/src/core/wu-proxy-sandbox.js +477 -476
  80. package/src/core/wu-sandbox.js +779 -779
  81. package/src/core/wu-script-executor.js +161 -113
  82. package/src/core/wu-snapshot-sandbox.js +227 -227
  83. package/src/core/wu-store.js +13 -3
  84. package/src/core/wu-strategies.js +256 -256
  85. package/src/core/wu-style-bridge.js +477 -477
  86. package/src/index.d.ts +317 -0
  87. package/src/index.js +234 -224
  88. package/src/utils/dependency-resolver.js +327 -327
@@ -1,328 +1,328 @@
1
- /**
2
- * 🔗 WU-DEPENDENCY-RESOLVER: SISTEMA DE RESOLUCIÓN DE DEPENDENCIAS
3
- * Maneja imports/exports entre micro-apps
4
- */
5
-
6
- import { logger } from '../core/wu-logger.js';
7
-
8
- export class WuDependencyResolver {
9
- constructor() {
10
- this.resolvedComponents = new Map();
11
- this.pendingResolutions = new Map();
12
-
13
- logger.debug('[WuDependencyResolver] 🔗 Dependency resolver initialized');
14
- }
15
-
16
- /**
17
- * Resolver todas las dependencias de una app
18
- * @param {Array} imports - Lista de imports del manifest
19
- * @param {Map} availableApps - Apps disponibles
20
- * @returns {Map} Componentes resueltos
21
- */
22
- async resolveAll(imports, availableApps) {
23
- logger.debug(`[WuDependencyResolver] 🔍 Resolving ${imports.length} dependencies...`);
24
-
25
- const resolved = new Map();
26
- const errors = [];
27
-
28
- for (const importPath of imports) {
29
- try {
30
- const component = await this.resolve(importPath, availableApps);
31
- resolved.set(importPath, component);
32
- logger.debug(`[WuDependencyResolver] ✅ Resolved: ${importPath}`);
33
- } catch (error) {
34
- errors.push({ import: importPath, error: error.message });
35
- logger.warn(`[WuDependencyResolver] ❌ Failed to resolve: ${importPath}`, error);
36
- }
37
- }
38
-
39
- if (errors.length > 0) {
40
- logger.warn(`[WuDependencyResolver] ⚠️ ${errors.length} dependencies failed to resolve:`, errors);
41
- }
42
-
43
- logger.debug(`[WuDependencyResolver] 🎉 Resolved ${resolved.size}/${imports.length} dependencies`);
44
- return resolved;
45
- }
46
-
47
- /**
48
- * Resolver una dependencia específica
49
- * @param {string} importPath - Ruta de import (ej: "shared.Button")
50
- * @param {Map} availableApps - Apps disponibles
51
- * @returns {Function} Componente resuelto
52
- */
53
- async resolve(importPath, availableApps) {
54
- // Verificar cache
55
- if (this.resolvedComponents.has(importPath)) {
56
- logger.debug(`[WuDependencyResolver] ⚡ Cache hit: ${importPath}`);
57
- return this.resolvedComponents.get(importPath);
58
- }
59
-
60
- // Verificar si ya está resolviendo
61
- if (this.pendingResolutions.has(importPath)) {
62
- logger.debug(`[WuDependencyResolver] ⏳ Waiting for pending resolution: ${importPath}`);
63
- return await this.pendingResolutions.get(importPath);
64
- }
65
-
66
- // Crear promesa de resolución
67
- const resolutionPromise = this.performResolution(importPath, availableApps);
68
- this.pendingResolutions.set(importPath, resolutionPromise);
69
-
70
- try {
71
- const component = await resolutionPromise;
72
- this.pendingResolutions.delete(importPath);
73
- this.resolvedComponents.set(importPath, component);
74
- return component;
75
- } catch (error) {
76
- this.pendingResolutions.delete(importPath);
77
- throw error;
78
- }
79
- }
80
-
81
- /**
82
- * Realizar la resolución efectiva
83
- * @param {string} importPath - Ruta de import
84
- * @param {Map} availableApps - Apps disponibles
85
- * @returns {Function} Componente resuelto
86
- */
87
- async performResolution(importPath, availableApps) {
88
- const [appName, componentName] = importPath.split('.');
89
-
90
- if (!appName || !componentName) {
91
- throw new Error(`Invalid import format: ${importPath}. Use "app.component"`);
92
- }
93
-
94
- // Buscar la app
95
- const app = availableApps.get(appName);
96
- if (!app) {
97
- throw new Error(`App not found: ${appName}`);
98
- }
99
-
100
- // Buscar el export en el manifest
101
- const manifest = app.manifest;
102
- const exportPath = manifest?.wu?.exports?.[componentName];
103
-
104
- if (!exportPath) {
105
- throw new Error(`Component ${componentName} not exported by ${appName}`);
106
- }
107
-
108
- // Cargar el componente usando el loader de la app
109
- const loader = app.loader || this.getDefaultLoader();
110
- const component = await loader.loadComponent(app.url, exportPath);
111
-
112
- if (!component) {
113
- throw new Error(`Failed to load component: ${importPath}`);
114
- }
115
-
116
- return component;
117
- }
118
-
119
- /**
120
- * Obtener loader por defecto si la app no tiene uno
121
- */
122
- getDefaultLoader() {
123
- if (!this._defaultLoader) {
124
- // Crear un loader básico si no hay uno disponible
125
- this._defaultLoader = {
126
- loadComponent: async (appUrl, componentPath) => {
127
- const fullUrl = `${appUrl}/${componentPath}`;
128
- const response = await fetch(fullUrl);
129
-
130
- if (!response.ok) {
131
- throw new Error(`Failed to fetch: ${fullUrl}`);
132
- }
133
-
134
- const code = await response.text();
135
-
136
- // Evaluar código del componente
137
- const componentFunction = new Function('require', 'module', 'exports', `
138
- ${code}
139
- return typeof module.exports === 'function' ? module.exports :
140
- typeof module.exports === 'object' && module.exports.default ? module.exports.default :
141
- exports.default || exports;
142
- `);
143
-
144
- const fakeModule = { exports: {} };
145
- const fakeRequire = () => ({});
146
-
147
- return componentFunction(fakeRequire, fakeModule, fakeModule.exports);
148
- }
149
- };
150
- }
151
- return this._defaultLoader;
152
- }
153
-
154
- /**
155
- * Validar dependencias de una app
156
- * @param {Array} imports - Lista de imports
157
- * @param {Map} availableApps - Apps disponibles
158
- * @returns {Object} Resultado de validación
159
- */
160
- validate(imports, availableApps) {
161
- const result = {
162
- valid: [],
163
- invalid: [],
164
- missing: [],
165
- circular: []
166
- };
167
-
168
- for (const importPath of imports) {
169
- const [appName, componentName] = importPath.split('.');
170
-
171
- // Validar formato
172
- if (!appName || !componentName) {
173
- result.invalid.push({
174
- import: importPath,
175
- reason: 'Invalid format. Use "app.component"'
176
- });
177
- continue;
178
- }
179
-
180
- // Validar que la app existe
181
- const app = availableApps.get(appName);
182
- if (!app) {
183
- result.missing.push({
184
- import: importPath,
185
- app: appName,
186
- reason: 'App not registered'
187
- });
188
- continue;
189
- }
190
-
191
- // Validar que el export existe
192
- const manifest = app.manifest;
193
- const exportExists = manifest?.wu?.exports?.[componentName];
194
-
195
- if (!exportExists) {
196
- result.invalid.push({
197
- import: importPath,
198
- reason: `Component ${componentName} not exported by ${appName}`
199
- });
200
- continue;
201
- }
202
-
203
- result.valid.push({
204
- import: importPath,
205
- app: appName,
206
- component: componentName,
207
- path: exportExists
208
- });
209
- }
210
-
211
- // Detectar dependencias circulares
212
- result.circular = this.detectCircularDependencies(imports, availableApps);
213
-
214
- return result;
215
- }
216
-
217
- /**
218
- * Detectar dependencias circulares
219
- * @param {Array} imports - Lista de imports
220
- * @param {Map} availableApps - Apps disponibles
221
- * @returns {Array} Dependencias circulares encontradas
222
- */
223
- detectCircularDependencies(imports, availableApps) {
224
- const circular = [];
225
- const visited = new Set();
226
- const visiting = new Set();
227
-
228
- const visit = (appName, path = []) => {
229
- if (visiting.has(appName)) {
230
- // Encontrada dependencia circular
231
- const circularPath = [...path, appName];
232
- circular.push(circularPath);
233
- return;
234
- }
235
-
236
- if (visited.has(appName)) {
237
- return;
238
- }
239
-
240
- visiting.add(appName);
241
- const currentPath = [...path, appName];
242
-
243
- // Buscar las dependencias de esta app
244
- const app = availableApps.get(appName);
245
- if (app && app.manifest?.wu?.imports) {
246
- for (const importPath of app.manifest.wu.imports) {
247
- const [depAppName] = importPath.split('.');
248
- if (depAppName) {
249
- visit(depAppName, currentPath);
250
- }
251
- }
252
- }
253
-
254
- visiting.delete(appName);
255
- visited.add(appName);
256
- };
257
-
258
- // Visitar todas las apps
259
- for (const app of availableApps.keys()) {
260
- visit(app);
261
- }
262
-
263
- return circular;
264
- }
265
-
266
- /**
267
- * Crear wrapper para componente compartido
268
- * @param {Function} component - Componente original
269
- * @param {string} importPath - Ruta de import
270
- * @returns {Function} Componente wrapper
271
- */
272
- createComponentWrapper(component, importPath) {
273
- return function WuSharedComponent(props) {
274
- logger.debug(`[WuDependencyResolver] 🧩 Rendering shared component: ${importPath}`);
275
-
276
- try {
277
- return component(props);
278
- } catch (error) {
279
- console.error(`[WuDependencyResolver] ❌ Error in shared component ${importPath}:`, error);
280
-
281
- // Componente de error fallback
282
- return {
283
- type: 'div',
284
- props: {
285
- style: {
286
- padding: '10px',
287
- border: '1px solid #ff6b6b',
288
- borderRadius: '4px',
289
- background: '#ffe0e0',
290
- color: '#d63031'
291
- },
292
- children: `Error in shared component: ${importPath}`
293
- }
294
- };
295
- }
296
- };
297
- }
298
-
299
- /**
300
- * Limpiar cache de dependencias
301
- * @param {string} pattern - Patrón opcional
302
- */
303
- clearCache(pattern) {
304
- if (pattern) {
305
- const regex = new RegExp(pattern);
306
- for (const [importPath] of this.resolvedComponents) {
307
- if (regex.test(importPath)) {
308
- this.resolvedComponents.delete(importPath);
309
- logger.debug(`[WuDependencyResolver] 🗑️ Cleared cache for: ${importPath}`);
310
- }
311
- }
312
- } else {
313
- this.resolvedComponents.clear();
314
- logger.debug(`[WuDependencyResolver] 🗑️ Dependency cache cleared completely`);
315
- }
316
- }
317
-
318
- /**
319
- * Obtener estadísticas del resolver
320
- */
321
- getStats() {
322
- return {
323
- resolved: this.resolvedComponents.size,
324
- pending: this.pendingResolutions.size,
325
- components: Array.from(this.resolvedComponents.keys())
326
- };
327
- }
1
+ /**
2
+ * 🔗 WU-DEPENDENCY-RESOLVER: SISTEMA DE RESOLUCIÓN DE DEPENDENCIAS
3
+ * Maneja imports/exports entre micro-apps
4
+ */
5
+
6
+ import { logger } from '../core/wu-logger.js';
7
+
8
+ export class WuDependencyResolver {
9
+ constructor() {
10
+ this.resolvedComponents = new Map();
11
+ this.pendingResolutions = new Map();
12
+
13
+ logger.debug('[WuDependencyResolver] 🔗 Dependency resolver initialized');
14
+ }
15
+
16
+ /**
17
+ * Resolver todas las dependencias de una app
18
+ * @param {Array} imports - Lista de imports del manifest
19
+ * @param {Map} availableApps - Apps disponibles
20
+ * @returns {Map} Componentes resueltos
21
+ */
22
+ async resolveAll(imports, availableApps) {
23
+ logger.debug(`[WuDependencyResolver] 🔍 Resolving ${imports.length} dependencies...`);
24
+
25
+ const resolved = new Map();
26
+ const errors = [];
27
+
28
+ for (const importPath of imports) {
29
+ try {
30
+ const component = await this.resolve(importPath, availableApps);
31
+ resolved.set(importPath, component);
32
+ logger.debug(`[WuDependencyResolver] ✅ Resolved: ${importPath}`);
33
+ } catch (error) {
34
+ errors.push({ import: importPath, error: error.message });
35
+ logger.warn(`[WuDependencyResolver] ❌ Failed to resolve: ${importPath}`, error);
36
+ }
37
+ }
38
+
39
+ if (errors.length > 0) {
40
+ logger.warn(`[WuDependencyResolver] ⚠️ ${errors.length} dependencies failed to resolve:`, errors);
41
+ }
42
+
43
+ logger.debug(`[WuDependencyResolver] 🎉 Resolved ${resolved.size}/${imports.length} dependencies`);
44
+ return resolved;
45
+ }
46
+
47
+ /**
48
+ * Resolver una dependencia específica
49
+ * @param {string} importPath - Ruta de import (ej: "shared.Button")
50
+ * @param {Map} availableApps - Apps disponibles
51
+ * @returns {Function} Componente resuelto
52
+ */
53
+ async resolve(importPath, availableApps) {
54
+ // Verificar cache
55
+ if (this.resolvedComponents.has(importPath)) {
56
+ logger.debug(`[WuDependencyResolver] ⚡ Cache hit: ${importPath}`);
57
+ return this.resolvedComponents.get(importPath);
58
+ }
59
+
60
+ // Verificar si ya está resolviendo
61
+ if (this.pendingResolutions.has(importPath)) {
62
+ logger.debug(`[WuDependencyResolver] ⏳ Waiting for pending resolution: ${importPath}`);
63
+ return await this.pendingResolutions.get(importPath);
64
+ }
65
+
66
+ // Crear promesa de resolución
67
+ const resolutionPromise = this.performResolution(importPath, availableApps);
68
+ this.pendingResolutions.set(importPath, resolutionPromise);
69
+
70
+ try {
71
+ const component = await resolutionPromise;
72
+ this.pendingResolutions.delete(importPath);
73
+ this.resolvedComponents.set(importPath, component);
74
+ return component;
75
+ } catch (error) {
76
+ this.pendingResolutions.delete(importPath);
77
+ throw error;
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Realizar la resolución efectiva
83
+ * @param {string} importPath - Ruta de import
84
+ * @param {Map} availableApps - Apps disponibles
85
+ * @returns {Function} Componente resuelto
86
+ */
87
+ async performResolution(importPath, availableApps) {
88
+ const [appName, componentName] = importPath.split('.');
89
+
90
+ if (!appName || !componentName) {
91
+ throw new Error(`Invalid import format: ${importPath}. Use "app.component"`);
92
+ }
93
+
94
+ // Buscar la app
95
+ const app = availableApps.get(appName);
96
+ if (!app) {
97
+ throw new Error(`App not found: ${appName}`);
98
+ }
99
+
100
+ // Buscar el export en el manifest
101
+ const manifest = app.manifest;
102
+ const exportPath = manifest?.wu?.exports?.[componentName];
103
+
104
+ if (!exportPath) {
105
+ throw new Error(`Component ${componentName} not exported by ${appName}`);
106
+ }
107
+
108
+ // Cargar el componente usando el loader de la app
109
+ const loader = app.loader || this.getDefaultLoader();
110
+ const component = await loader.loadComponent(app.url, exportPath);
111
+
112
+ if (!component) {
113
+ throw new Error(`Failed to load component: ${importPath}`);
114
+ }
115
+
116
+ return component;
117
+ }
118
+
119
+ /**
120
+ * Obtener loader por defecto si la app no tiene uno
121
+ */
122
+ getDefaultLoader() {
123
+ if (!this._defaultLoader) {
124
+ // Crear un loader básico si no hay uno disponible
125
+ this._defaultLoader = {
126
+ loadComponent: async (appUrl, componentPath) => {
127
+ const fullUrl = `${appUrl}/${componentPath}`;
128
+ const response = await fetch(fullUrl);
129
+
130
+ if (!response.ok) {
131
+ throw new Error(`Failed to fetch: ${fullUrl}`);
132
+ }
133
+
134
+ const code = await response.text();
135
+
136
+ // Evaluar código del componente
137
+ const componentFunction = new Function('require', 'module', 'exports', `
138
+ ${code}
139
+ return typeof module.exports === 'function' ? module.exports :
140
+ typeof module.exports === 'object' && module.exports.default ? module.exports.default :
141
+ exports.default || exports;
142
+ `);
143
+
144
+ const fakeModule = { exports: {} };
145
+ const fakeRequire = () => ({});
146
+
147
+ return componentFunction(fakeRequire, fakeModule, fakeModule.exports);
148
+ }
149
+ };
150
+ }
151
+ return this._defaultLoader;
152
+ }
153
+
154
+ /**
155
+ * Validar dependencias de una app
156
+ * @param {Array} imports - Lista de imports
157
+ * @param {Map} availableApps - Apps disponibles
158
+ * @returns {Object} Resultado de validación
159
+ */
160
+ validate(imports, availableApps) {
161
+ const result = {
162
+ valid: [],
163
+ invalid: [],
164
+ missing: [],
165
+ circular: []
166
+ };
167
+
168
+ for (const importPath of imports) {
169
+ const [appName, componentName] = importPath.split('.');
170
+
171
+ // Validar formato
172
+ if (!appName || !componentName) {
173
+ result.invalid.push({
174
+ import: importPath,
175
+ reason: 'Invalid format. Use "app.component"'
176
+ });
177
+ continue;
178
+ }
179
+
180
+ // Validar que la app existe
181
+ const app = availableApps.get(appName);
182
+ if (!app) {
183
+ result.missing.push({
184
+ import: importPath,
185
+ app: appName,
186
+ reason: 'App not registered'
187
+ });
188
+ continue;
189
+ }
190
+
191
+ // Validar que el export existe
192
+ const manifest = app.manifest;
193
+ const exportExists = manifest?.wu?.exports?.[componentName];
194
+
195
+ if (!exportExists) {
196
+ result.invalid.push({
197
+ import: importPath,
198
+ reason: `Component ${componentName} not exported by ${appName}`
199
+ });
200
+ continue;
201
+ }
202
+
203
+ result.valid.push({
204
+ import: importPath,
205
+ app: appName,
206
+ component: componentName,
207
+ path: exportExists
208
+ });
209
+ }
210
+
211
+ // Detectar dependencias circulares
212
+ result.circular = this.detectCircularDependencies(imports, availableApps);
213
+
214
+ return result;
215
+ }
216
+
217
+ /**
218
+ * Detectar dependencias circulares
219
+ * @param {Array} imports - Lista de imports
220
+ * @param {Map} availableApps - Apps disponibles
221
+ * @returns {Array} Dependencias circulares encontradas
222
+ */
223
+ detectCircularDependencies(imports, availableApps) {
224
+ const circular = [];
225
+ const visited = new Set();
226
+ const visiting = new Set();
227
+
228
+ const visit = (appName, path = []) => {
229
+ if (visiting.has(appName)) {
230
+ // Encontrada dependencia circular
231
+ const circularPath = [...path, appName];
232
+ circular.push(circularPath);
233
+ return;
234
+ }
235
+
236
+ if (visited.has(appName)) {
237
+ return;
238
+ }
239
+
240
+ visiting.add(appName);
241
+ const currentPath = [...path, appName];
242
+
243
+ // Buscar las dependencias de esta app
244
+ const app = availableApps.get(appName);
245
+ if (app && app.manifest?.wu?.imports) {
246
+ for (const importPath of app.manifest.wu.imports) {
247
+ const [depAppName] = importPath.split('.');
248
+ if (depAppName) {
249
+ visit(depAppName, currentPath);
250
+ }
251
+ }
252
+ }
253
+
254
+ visiting.delete(appName);
255
+ visited.add(appName);
256
+ };
257
+
258
+ // Visitar todas las apps
259
+ for (const app of availableApps.keys()) {
260
+ visit(app);
261
+ }
262
+
263
+ return circular;
264
+ }
265
+
266
+ /**
267
+ * Crear wrapper para componente compartido
268
+ * @param {Function} component - Componente original
269
+ * @param {string} importPath - Ruta de import
270
+ * @returns {Function} Componente wrapper
271
+ */
272
+ createComponentWrapper(component, importPath) {
273
+ return function WuSharedComponent(props) {
274
+ logger.debug(`[WuDependencyResolver] 🧩 Rendering shared component: ${importPath}`);
275
+
276
+ try {
277
+ return component(props);
278
+ } catch (error) {
279
+ console.error(`[WuDependencyResolver] ❌ Error in shared component ${importPath}:`, error);
280
+
281
+ // Componente de error fallback
282
+ return {
283
+ type: 'div',
284
+ props: {
285
+ style: {
286
+ padding: '10px',
287
+ border: '1px solid #ff6b6b',
288
+ borderRadius: '4px',
289
+ background: '#ffe0e0',
290
+ color: '#d63031'
291
+ },
292
+ children: `Error in shared component: ${importPath}`
293
+ }
294
+ };
295
+ }
296
+ };
297
+ }
298
+
299
+ /**
300
+ * Limpiar cache de dependencias
301
+ * @param {string} pattern - Patrón opcional
302
+ */
303
+ clearCache(pattern) {
304
+ if (pattern) {
305
+ const regex = new RegExp(pattern);
306
+ for (const [importPath] of this.resolvedComponents) {
307
+ if (regex.test(importPath)) {
308
+ this.resolvedComponents.delete(importPath);
309
+ logger.debug(`[WuDependencyResolver] 🗑️ Cleared cache for: ${importPath}`);
310
+ }
311
+ }
312
+ } else {
313
+ this.resolvedComponents.clear();
314
+ logger.debug(`[WuDependencyResolver] 🗑️ Dependency cache cleared completely`);
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Obtener estadísticas del resolver
320
+ */
321
+ getStats() {
322
+ return {
323
+ resolved: this.resolvedComponents.size,
324
+ pending: this.pendingResolutions.size,
325
+ components: Array.from(this.resolvedComponents.keys())
326
+ };
327
+ }
328
328
  }