wu-framework 1.1.8 → 1.1.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wu-framework",
3
- "version": "1.1.8",
3
+ "version": "1.1.10",
4
4
  "description": "Universal Microfrontends Framework - 8 frameworks, zero config, Shadow DOM isolation",
5
5
  "main": "dist/wu-framework.cjs.js",
6
6
  "module": "src/index.js",
@@ -51,9 +51,15 @@
51
51
  "web-components",
52
52
  "shadow-dom",
53
53
  "universal",
54
- "zero-config"
54
+ "zero-config",
55
+ "ai",
56
+ "llm",
57
+ "webmcp",
58
+ "mcp",
59
+ "tool-calling",
60
+ "byol"
55
61
  ],
56
- "author": "Wu Framework Team",
62
+ "author": "Luis Garcia",
57
63
  "license": "MIT",
58
64
  "repository": {
59
65
  "type": "git",
@@ -62,7 +68,7 @@
62
68
  "bugs": {
63
69
  "url": "https://github.com/wu-framework/wu-framework/issues"
64
70
  },
65
- "homepage": "https://wu-framework.dev",
71
+ "homepage": "https://www.wu-framework.com",
66
72
  "engines": {
67
73
  "node": ">=16.0.0"
68
74
  },
@@ -35,25 +35,38 @@ async function ensureReact() {
35
35
 
36
36
  try {
37
37
  // Intentar obtener de window (común en microfrontends)
38
- if (typeof window !== 'undefined') {
39
- if (window.React && window.ReactDOM) {
40
- adapterState.React = window.React;
41
- adapterState.ReactDOM = window.ReactDOM;
38
+ if (typeof window !== 'undefined' && window.React && window.ReactDOM) {
39
+ adapterState.React = window.React;
40
+ adapterState.ReactDOM = window.ReactDOM;
41
+
42
+ // createRoot puede estar en window.ReactDOM (si importaron de react-dom/client)
43
+ // o no existir (si importaron de react-dom). Intentar ambos caminos.
44
+ if (window.ReactDOM.createRoot) {
42
45
  adapterState.createRoot = window.ReactDOM.createRoot;
43
- adapterState.initialized = true;
44
- return true;
46
+ } else {
47
+ // Fallback: importar react-dom/client para obtener createRoot
48
+ try {
49
+ const clientModule = await import('react-dom/client');
50
+ adapterState.createRoot = (clientModule.default || clientModule).createRoot;
51
+ } catch {
52
+ console.error('[WuReact] createRoot not found. Expose window.ReactDOM from "react-dom/client", not "react-dom".');
53
+ return false;
54
+ }
45
55
  }
56
+
57
+ adapterState.initialized = true;
58
+ return true;
46
59
  }
47
60
 
48
61
  // Intentar import dinámico
49
- const [React, ReactDOM] = await Promise.all([
62
+ const [React, ReactDOMClient] = await Promise.all([
50
63
  import('react'),
51
64
  import('react-dom/client')
52
65
  ]);
53
66
 
54
67
  adapterState.React = React.default || React;
55
- adapterState.ReactDOM = ReactDOM;
56
- adapterState.createRoot = ReactDOM.createRoot;
68
+ adapterState.ReactDOM = ReactDOMClient.default || ReactDOMClient;
69
+ adapterState.createRoot = (ReactDOMClient.default || ReactDOMClient).createRoot;
57
70
  adapterState.initialized = true;
58
71
  return true;
59
72
 
@@ -280,65 +293,70 @@ function createWuSlot(React) {
280
293
 
281
294
  const actualAppName = appName || name;
282
295
 
283
- const mountMicrofrontend = useCallback(async () => {
284
- if (!containerRef.current) return;
285
-
286
- try {
287
- setLoading(true);
288
- setError(null);
289
-
290
- const wu = getWuInstance();
291
- if (!wu) {
292
- throw new Error('Wu Framework not initialized');
293
- }
294
-
295
- // Crear container interno
296
- const containerId = `wu-slot-${actualAppName}-${Date.now()}`;
297
- const innerContainer = document.createElement('div');
298
- innerContainer.id = containerId;
299
- innerContainer.style.width = '100%';
300
- innerContainer.style.height = '100%';
301
- containerRef.current.innerHTML = '';
302
- containerRef.current.appendChild(innerContainer);
303
-
304
- // Crear y montar la app
305
- const app = wu.app(actualAppName, {
306
- url,
307
- container: `#${containerId}`,
308
- autoInit: true
309
- });
310
-
311
- appInstanceRef.current = app;
312
- await app.mount();
296
+ useEffect(() => {
297
+ let cancelled = false;
298
+ const containerId = `wu-slot-${actualAppName}-${Math.random().toString(36).slice(2, 8)}`;
299
+
300
+ // Delay de 50ms para compatibilidad con React 18/19 StrictMode.
301
+ // En StrictMode el primer efecto se cancela inmediatamente (cancelled = true,
302
+ // clearTimeout) y solo el segundo efecto monta; evita doble-mount y
303
+ // "[Wu] App not mounted" en primera carga.
304
+ const timer = setTimeout(async () => {
305
+ if (cancelled || !containerRef.current) return;
306
+
307
+ try {
308
+ setLoading(true);
309
+ setError(null);
310
+
311
+ const wu = getWuInstance();
312
+ if (!wu) {
313
+ throw new Error('Wu Framework not initialized');
314
+ }
313
315
 
314
- setLoading(false);
316
+ // Crear container interno
317
+ const innerContainer = document.createElement('div');
318
+ innerContainer.id = containerId;
319
+ innerContainer.style.width = '100%';
320
+ innerContainer.style.height = '100%';
321
+ containerRef.current.innerHTML = '';
322
+ containerRef.current.appendChild(innerContainer);
315
323
 
316
- if (onLoad) onLoad({ name: actualAppName, url });
317
- if (onMount) onMount({ name: actualAppName, container: innerContainer });
324
+ // Montar usando wu.mount() (wu.init() ya se llamó en el shell)
325
+ await wu.mount(actualAppName, `#${containerId}`);
318
326
 
319
- } catch (err) {
320
- console.error(`[WuSlot] Error loading ${actualAppName}:`, err);
321
- setError(err.message || 'Failed to load microfrontend');
322
- setLoading(false);
327
+ if (!cancelled) {
328
+ appInstanceRef.current = actualAppName;
329
+ setLoading(false);
323
330
 
324
- if (onError) onError(err);
325
- }
326
- }, [actualAppName, url, onLoad, onError, onMount]);
331
+ if (onLoad) onLoad({ name: actualAppName, url });
332
+ if (onMount) onMount({ name: actualAppName, container: innerContainer });
333
+ }
334
+ } catch (err) {
335
+ if (!cancelled) {
336
+ console.error(`[WuSlot] Error loading ${actualAppName}:`, err);
337
+ setError(err.message || 'Failed to load microfrontend');
338
+ setLoading(false);
327
339
 
328
- useEffect(() => {
329
- mountMicrofrontend();
340
+ if (onError) onError(err);
341
+ }
342
+ }
343
+ }, 50);
330
344
 
331
345
  return () => {
346
+ cancelled = true;
347
+ clearTimeout(timer);
348
+
332
349
  if (appInstanceRef.current) {
333
350
  if (onUnmount) onUnmount({ name: actualAppName });
334
351
 
335
- appInstanceRef.current.unmount().catch(err => {
336
- console.warn(`[WuSlot] Error unmounting ${actualAppName}:`, err);
337
- });
352
+ const wu = getWuInstance();
353
+ if (wu) {
354
+ wu.unmount(actualAppName).catch(() => {});
355
+ }
338
356
  appInstanceRef.current = null;
339
357
  }
340
358
  };
341
- }, [mountMicrofrontend, actualAppName, onUnmount]);
359
+ }, [actualAppName, url, onLoad, onError, onMount, onUnmount]);
342
360
 
343
361
  // Render de error
344
362
  if (error) {