wu-framework 1.0.5 → 1.1.0

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 CHANGED
@@ -9,11 +9,13 @@ Wu Framework es la librería de microfrontends más simple y poderosa del mercad
9
9
  | Característica | Module Federation | qiankun | **Wu Framework** |
10
10
  |---|---|---|---|
11
11
  | **Setup** | Webpack config complejo | Configuración manual | **Zero config** |
12
- | **Framework Support** | React-first | Multi framework | **Cualquier framework** |
12
+ | **Framework Support** | React-first | Multi framework | **8 frameworks nativos** |
13
13
  | **Bundler Required** | Solo Webpack 5 | Agnóstico pero complejo | **Ninguno** |
14
14
  | **CSS Isolation** | Básico | CSS hacks | **Shadow DOM nativo** |
15
+ | **JS Isolation** | ❌ | Proxy básico | **Proxy Sandbox completo** |
15
16
  | **Runtime Config** | ❌ | Limitado | **✅ Completamente dinámico** |
16
- | **API Complexity** | Alta | Media | **Súper simple** |
17
+ | **Self-Healing** | | | **✅ Auto-recovery** |
18
+ | **API Complexity** | Alta | Media | **1 línea de código** |
17
19
 
18
20
  ## 🎯 Instalación
19
21
 
@@ -23,15 +25,34 @@ npm install wu-framework
23
25
 
24
26
  **¡Y ya está!** Sin webpack config, sin plugins, sin configuración.
25
27
 
26
- ## 🔥 Uso Básico
28
+ ---
29
+
30
+ ## 🎨 Frameworks Soportados
31
+
32
+ Wu Framework incluye **adapters nativos** para los frameworks más populares:
33
+
34
+ | Framework | Adapter | Registro |
35
+ |-----------|---------|----------|
36
+ | ⚛️ React | `wuReact` | `wuReact.register('app', App)` |
37
+ | 💚 Vue | `wuVue` | `wuVue.register('app', App)` |
38
+ | 🅰️ Angular | `wuAngular` | `wuAngular.register('app', AppModule)` |
39
+ | 🧡 Svelte | `wuSvelte` | `wuSvelte.register('app', App)` |
40
+ | ⚡ Preact | `wuPreact` | `wuPreact.register('app', App)` |
41
+ | 💎 Solid.js | `wuSolid` | `wuSolid.register('app', App)` |
42
+ | 🔥 Lit | `wuLit` | `wuLit.register('app', MyElement)` |
43
+ | 📦 Vanilla JS | `wuVanilla` | `wuVanilla.register('app', config)` |
44
+
45
+ ---
27
46
 
28
- ### Container App (Host)
47
+ ## 🔥 Quick Start
48
+
49
+ ### 1. Shell (Host Application)
29
50
 
30
51
  ```js
31
52
  import { wu } from 'wu-framework';
32
53
 
33
- // Inicializar con apps
34
- wu.init({
54
+ // Inicializar y montar microfrontends
55
+ await wu.init({
35
56
  apps: [
36
57
  { name: 'header', url: 'http://localhost:3001' },
37
58
  { name: 'sidebar', url: 'http://localhost:3002' },
@@ -39,521 +60,907 @@ wu.init({
39
60
  ]
40
61
  });
41
62
 
42
- // Montar en el DOM
43
- wu.mount('header', '#header-container');
44
- wu.mount('sidebar', '#sidebar-container');
45
- wu.mount('content', '#content-container');
63
+ await wu.mount('header', '#header-container');
64
+ await wu.mount('sidebar', '#sidebar-container');
65
+ await wu.mount('content', '#content-container');
46
66
  ```
47
67
 
48
- ### Micro App (Cualquier Framework)
68
+ ### 2. Micro App (1 línea de código)
49
69
 
50
- ```js
51
- import { wu } from 'wu-framework';
70
+ **React:**
71
+ ```tsx
72
+ import { wuReact } from 'wu-framework/adapters/react';
73
+ import App from './App';
52
74
 
53
- // React
54
- wu.define('header', {
55
- mount: (container) => {
56
- ReactDOM.render(<HeaderApp />, container);
57
- },
58
- unmount: (container) => {
59
- ReactDOM.unmountComponentAtNode(container);
60
- }
61
- });
75
+ wuReact.register('header', App);
76
+ ```
62
77
 
63
- // Vue
64
- wu.define('sidebar', {
65
- mount: (container) => {
66
- createApp(SidebarApp).mount(container);
67
- },
68
- unmount: (container) => {
69
- // Vue cleanup
70
- }
71
- });
78
+ **Vue:**
79
+ ```ts
80
+ import { wuVue } from 'wu-framework/adapters/vue';
81
+ import App from './App.vue';
72
82
 
73
- // Vanilla JS
74
- wu.define('content', {
75
- mount: (container) => {
76
- container.innerHTML = `
77
- <h1>Content App</h1>
78
- <p>Pure vanilla JavaScript!</p>
79
- `;
80
- },
81
- unmount: (container) => {
82
- container.innerHTML = '';
83
- }
84
- });
83
+ wuVue.register('sidebar', App);
85
84
  ```
86
85
 
87
- ## 📋 Wu Manifest (wu.json)
88
-
89
- Cada micro-app puede tener un archivo `wu.json` para configuración:
90
-
91
- ```json
92
- {
93
- "name": "header-app",
94
- "entry": "index.js",
95
- "wu": {
96
- "exports": {
97
- "HeaderComponent": "./components/Header",
98
- "useAuth": "./hooks/useAuth"
99
- },
100
- "imports": [
101
- "shared.Button",
102
- "shared.Theme"
103
- ],
104
- "routes": ["/header", "/nav"],
105
- "permissions": ["localStorage", "eventBus"]
106
- }
107
- }
86
+ **Angular:**
87
+ ```ts
88
+ import { wuAngular } from 'wu-framework/adapters/angular';
89
+ import { AppModule } from './app/app.module';
90
+
91
+ wuAngular.register('content', AppModule);
108
92
  ```
109
93
 
110
- ### Component Sharing
94
+ **¡Eso es todo!** El adapter se encarga de todo: detección de contexto, modo standalone, cleanup automático.
111
95
 
112
- ```js
113
- // Exportar componentes
114
- wu.define('shared', {
115
- mount: (container) => {
116
- // App shared con componentes reutilizables
117
- }
118
- });
96
+ ---
119
97
 
120
- // Usar componentes compartidos
121
- const Button = await wu.use('shared.Button');
122
- const Theme = await wu.use('shared.Theme');
123
- ```
98
+ ## ⚛️ React Adapter
124
99
 
125
- ## 🏗️ Arquitectura
100
+ ### Registro Básico
126
101
 
127
- Wu Framework usa **Shadow DOM nativo** para verdadero aislamiento:
102
+ ```tsx
103
+ import { wuReact } from 'wu-framework/adapters/react';
104
+ import App from './App';
128
105
 
106
+ wuReact.register('my-app', App);
129
107
  ```
130
- ┌─────────────────────────────────────┐
131
- │ Host Application │
132
- ├─────────────────────────────────────┤
133
- │ ┌─────────────┐ ┌─────────────┐ │
134
- │ │ #shadow-root│ │ #shadow-root│ │
135
- │ ┌─────────┐│ │ ┌─────────┐│ │
136
- │ │Header ││ │ │Sidebar ││ │
137
- │ │(React) ││ │ │(Vue) ││ │
138
- │ └─────────┘│ │ └─────────┘│ │
139
- └─────────────┘ └─────────────┘ │
140
- └─────────────────────────────────────┘
108
+
109
+ ### Con Opciones
110
+
111
+ ```tsx
112
+ wuReact.register('my-app', App, {
113
+ strictMode: true, // Envolver en React.StrictMode
114
+ props: { theme: 'dark' }, // Props iniciales
115
+ standalone: true, // Ejecutar independiente si Wu no está
116
+ standaloneContainer: '#root',
117
+ onMount: (container) => console.log('Mounted!'),
118
+ onUnmount: (container) => console.log('Unmounted!')
119
+ });
141
120
  ```
142
121
 
143
- ### Ventajas del Shadow DOM:
122
+ ### Hooks para React
144
123
 
145
- - ✅ **CSS completamente aislado** - No hay conflictos de estilos
146
- - **JavaScript scope aislado** - Variables globales separadas
147
- - **DOM encapsulado** - No hay interferencia entre apps
148
- - ✅ **Performance nativo** - Sin overhead de hacks CSS
149
- - ✅ **Debugging fácil** - Cada app en su propio DevTools tree
124
+ ```tsx
125
+ import React from 'react';
126
+ import { createUseWuEvents, createUseWuStore } from 'wu-framework/adapters/react';
150
127
 
151
- ## 🎨 Ejemplos de Frameworks
128
+ const useWuEvents = createUseWuEvents(React);
129
+ const useWuStore = createUseWuStore(React);
152
130
 
153
- ### React + TypeScript
131
+ function MyComponent() {
132
+ const { emit, on } = useWuEvents();
133
+ const { state, setState } = useWuStore('user');
134
+
135
+ useEffect(() => {
136
+ const unsub = on('cart:updated', (data) => {
137
+ console.log('Cart updated:', data);
138
+ });
139
+ return unsub;
140
+ }, [on]);
141
+
142
+ return (
143
+ <button onClick={() => emit('user:logout')}>
144
+ Logout {state?.name}
145
+ </button>
146
+ );
147
+ }
148
+ ```
149
+
150
+ ### Cargar Microfrontends en React (Shell)
154
151
 
155
152
  ```tsx
156
- // header-app/src/index.tsx
157
153
  import React from 'react';
158
- import ReactDOM from 'react-dom';
159
- import { wu } from 'wu-framework';
154
+ import { createWuSlot } from 'wu-framework/adapters/react';
155
+
156
+ const WuSlot = createWuSlot(React);
157
+
158
+ function Shell() {
159
+ return (
160
+ <div>
161
+ <WuSlot
162
+ name="header"
163
+ url="http://localhost:3001"
164
+ onLoad={() => console.log('Header loaded!')}
165
+ onError={(err) => console.error(err)}
166
+ />
167
+ <WuSlot name="content" url="http://localhost:3002" />
168
+ </div>
169
+ );
170
+ }
171
+ ```
160
172
 
161
- const HeaderApp: React.FC = () => (
162
- <header className="app-header">
163
- <h1>Header App (React)</h1>
164
- </header>
165
- );
173
+ ---
166
174
 
167
- wu.define('header', {
168
- mount: (container: HTMLElement) => {
169
- ReactDOM.render(<HeaderApp />, container);
170
- },
171
- unmount: (container: HTMLElement) => {
172
- ReactDOM.unmountComponentAtNode(container);
175
+ ## 💚 Vue Adapter
176
+
177
+ ### Registro Básico
178
+
179
+ ```ts
180
+ import { wuVue } from 'wu-framework/adapters/vue';
181
+ import App from './App.vue';
182
+
183
+ wuVue.register('my-app', App);
184
+ ```
185
+
186
+ ### Con Plugins (Pinia, Router, etc.)
187
+
188
+ ```ts
189
+ import { wuVue } from 'wu-framework/adapters/vue';
190
+ import { createPinia } from 'pinia';
191
+ import router from './router';
192
+ import App from './App.vue';
193
+
194
+ wuVue.register('my-app', App, {
195
+ setup: (app) => {
196
+ app.use(createPinia());
197
+ app.use(router);
173
198
  }
174
199
  });
175
200
  ```
176
201
 
177
- ### Vue 3 + Composition API
202
+ ### Composables para Vue
178
203
 
179
204
  ```vue
180
- <!-- sidebar-app/src/App.vue -->
205
+ <script setup>
206
+ import { onMounted, onUnmounted } from 'vue';
207
+ import { useWuEvents, useWuStore } from 'wu-framework/adapters/vue';
208
+
209
+ const { emit, on, cleanup } = useWuEvents();
210
+ const { state, setState } = useWuStore('cart');
211
+
212
+ onMounted(() => {
213
+ on('user:login', (data) => console.log('Login:', data));
214
+ });
215
+
216
+ onUnmounted(() => cleanup());
217
+ </script>
218
+
181
219
  <template>
182
- <aside class="app-sidebar">
183
- <h2>Sidebar App (Vue)</h2>
184
- <nav>
185
- <ul>
186
- <li v-for="item in items" :key="item.id">
187
- {{ item.name }}
188
- </li>
189
- </ul>
190
- </nav>
191
- </aside>
220
+ <div>
221
+ <p>Items: {{ state?.items?.length }}</p>
222
+ <button @click="emit('cart:clear')">Clear Cart</button>
223
+ </div>
192
224
  </template>
225
+ ```
193
226
 
194
- <script setup>
195
- import { ref } from 'vue';
227
+ ### Cargar Microfrontends en Vue (Shell)
196
228
 
197
- const items = ref([
198
- { id: 1, name: 'Home' },
199
- { id: 2, name: 'About' },
200
- { id: 3, name: 'Contact' }
201
- ]);
229
+ ```vue
230
+ <script setup>
231
+ import { WuSlot } from 'wu-framework/adapters/vue';
202
232
  </script>
233
+
234
+ <template>
235
+ <div>
236
+ <WuSlot
237
+ name="header"
238
+ url="http://localhost:3001"
239
+ @load="onLoad"
240
+ @error="onError"
241
+ />
242
+ <WuSlot name="sidebar" url="http://localhost:3002" />
243
+ </div>
244
+ </template>
203
245
  ```
204
246
 
205
- ```js
206
- // sidebar-app/src/index.js
247
+ ### Plugin Global
248
+
249
+ ```ts
207
250
  import { createApp } from 'vue';
208
- import { wu } from 'wu-framework';
209
- import App from './App.vue';
251
+ import { wuVuePlugin } from 'wu-framework/adapters/vue';
210
252
 
211
- let app;
253
+ const app = createApp(App);
254
+ app.use(wuVuePlugin); // Registra <WuSlot> globalmente
255
+ ```
212
256
 
213
- wu.define('sidebar', {
214
- mount: (container) => {
215
- app = createApp(App);
216
- app.mount(container);
217
- },
218
- unmount: (container) => {
219
- if (app) {
220
- app.unmount();
221
- app = null;
222
- }
223
- }
257
+ ---
258
+
259
+ ## 🅰️ Angular Adapter
260
+
261
+ ### Registro con NgModule
262
+
263
+ ```ts
264
+ import { wuAngular } from 'wu-framework/adapters/angular';
265
+ import { AppModule } from './app/app.module';
266
+
267
+ wuAngular.register('my-app', AppModule);
268
+ ```
269
+
270
+ ### Registro con Standalone Components (Angular 14+)
271
+
272
+ ```ts
273
+ import { wuAngular } from 'wu-framework/adapters/angular';
274
+ import { AppComponent } from './app/app.component';
275
+ import { appConfig } from './app/app.config';
276
+
277
+ wuAngular.registerStandalone('my-app', AppComponent, {
278
+ appConfig
224
279
  });
225
280
  ```
226
281
 
227
- ### Angular
282
+ ### Servicio para Componentes
228
283
 
229
- ```typescript
230
- // content-app/src/main.ts
231
- import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
232
- import { wu } from 'wu-framework';
233
- import { AppModule } from './app/app.module';
284
+ ```ts
285
+ import { Component, OnInit, OnDestroy } from '@angular/core';
286
+ import { createWuService } from 'wu-framework/adapters/angular';
287
+
288
+ @Component({
289
+ selector: 'app-root',
290
+ template: `<button (click)="sendEvent()">Send Event</button>`
291
+ })
292
+ export class AppComponent implements OnInit, OnDestroy {
293
+ private wuService = createWuService();
234
294
 
235
- let platformRef: any;
295
+ ngOnInit() {
296
+ this.wuService.on('user:login', (data) => {
297
+ console.log('User logged in:', data);
298
+ });
299
+ }
236
300
 
237
- wu.define('content', {
238
- mount: async (container: HTMLElement) => {
239
- // Crear elemento para Angular
240
- const appElement = document.createElement('app-root');
241
- container.appendChild(appElement);
301
+ sendEvent() {
302
+ this.wuService.emit('app:ready', { timestamp: Date.now() });
303
+ }
242
304
 
243
- // Bootstrap Angular
244
- platformRef = await platformBrowserDynamic().bootstrapModule(AppModule);
245
- },
246
- unmount: (container: HTMLElement) => {
247
- if (platformRef) {
248
- platformRef.destroy();
249
- platformRef = null;
250
- }
251
- container.innerHTML = '';
305
+ ngOnDestroy() {
306
+ this.wuService.destroy();
252
307
  }
253
- });
308
+ }
254
309
  ```
255
310
 
256
- ### Svelte
311
+ ---
312
+
313
+ ## 🧡 Svelte Adapter
314
+
315
+ ### Registro Básico
257
316
 
258
317
  ```js
259
- // footer-app/src/index.js
260
- import { wu } from 'wu-framework';
318
+ import { wuSvelte } from 'wu-framework/adapters/svelte';
261
319
  import App from './App.svelte';
262
320
 
263
- let app;
321
+ wuSvelte.register('my-app', App);
322
+ ```
264
323
 
265
- wu.define('footer', {
266
- mount: (container) => {
267
- app = new App({
268
- target: container,
269
- props: {
270
- name: 'Footer App'
271
- }
272
- });
273
- },
274
- unmount: (container) => {
275
- if (app) {
276
- app.$destroy();
277
- app = null;
278
- }
324
+ ### Svelte 5 (con runes)
325
+
326
+ ```js
327
+ import { wuSvelte } from 'wu-framework/adapters/svelte';
328
+ import App from './App.svelte';
329
+
330
+ wuSvelte.registerSvelte5('my-app', App);
331
+ ```
332
+
333
+ ### Stores Reactivos
334
+
335
+ ```svelte
336
+ <script>
337
+ import { createWuStore, useWuEvents } from 'wu-framework/adapters/svelte';
338
+ import { onDestroy } from 'svelte';
339
+
340
+ // Store reactivo (compatible con $store)
341
+ const userStore = createWuStore('user');
342
+
343
+ // Eventos
344
+ const { emit, on, cleanup } = useWuEvents();
345
+
346
+ on('cart:updated', (data) => {
347
+ console.log('Cart updated:', data);
348
+ });
349
+
350
+ onDestroy(cleanup);
351
+ </script>
352
+
353
+ <p>Hello, {$userStore?.name}</p>
354
+ <button on:click={() => emit('user:logout')}>Logout</button>
355
+ ```
356
+
357
+ ---
358
+
359
+ ## ⚡ Preact Adapter
360
+
361
+ ### Registro Básico
362
+
363
+ ```jsx
364
+ import { wuPreact } from 'wu-framework/adapters/preact';
365
+ import App from './App';
366
+
367
+ wuPreact.register('my-app', App);
368
+ ```
369
+
370
+ ### Compatible con React (preact/compat)
371
+
372
+ ```jsx
373
+ import { wuPreact } from 'wu-framework/adapters/preact';
374
+ import App from './App'; // Componente estilo React
375
+
376
+ wuPreact.registerCompat('my-app', App);
377
+ ```
378
+
379
+ ### Hooks
380
+
381
+ ```jsx
382
+ import { h } from 'preact';
383
+ import { useState, useEffect, useCallback, useRef } from 'preact/hooks';
384
+ import { createUseWuEvents, createUseWuStore } from 'wu-framework/adapters/preact';
385
+
386
+ const useWuEvents = createUseWuEvents({ useCallback, useEffect, useRef });
387
+ const useWuStore = createUseWuStore({ useState, useCallback, useEffect });
388
+
389
+ function MyComponent() {
390
+ const { emit, on } = useWuEvents();
391
+ const { state } = useWuStore('user');
392
+
393
+ return <div>Hello {state?.name}</div>;
394
+ }
395
+ ```
396
+
397
+ ---
398
+
399
+ ## 💎 Solid.js Adapter
400
+
401
+ ### Registro Básico
402
+
403
+ ```jsx
404
+ import { wuSolid } from 'wu-framework/adapters/solid';
405
+ import App from './App';
406
+
407
+ wuSolid.register('my-app', App);
408
+ ```
409
+
410
+ ### Stores Reactivos
411
+
412
+ ```jsx
413
+ import { createWuStore, createWuEvent } from 'wu-framework/adapters/solid';
414
+
415
+ function MyComponent() {
416
+ // Store reactivo
417
+ const [user, setUser] = createWuStore('user');
418
+
419
+ // Eventos reactivos
420
+ const lastEvent = createWuEvent('notification:*');
421
+
422
+ return (
423
+ <div>
424
+ <p>Hello, {user()?.name}</p>
425
+ <Show when={lastEvent()}>
426
+ <p>Last notification: {lastEvent()?.data}</p>
427
+ </Show>
428
+ <button onClick={() => setUser('name', 'John')}>
429
+ Set Name
430
+ </button>
431
+ </div>
432
+ );
433
+ }
434
+ ```
435
+
436
+ ---
437
+
438
+ ## 🔥 Lit Adapter (Web Components)
439
+
440
+ ### Registro con LitElement
441
+
442
+ ```js
443
+ import { LitElement, html, css } from 'lit';
444
+ import { wuLit } from 'wu-framework/adapters/lit';
445
+
446
+ class MyApp extends LitElement {
447
+ static styles = css`
448
+ :host { display: block; padding: 16px; }
449
+ `;
450
+
451
+ render() {
452
+ return html`<h1>Hello from Lit!</h1>`;
279
453
  }
280
- });
454
+ }
455
+
456
+ wuLit.register('my-app', MyApp);
281
457
  ```
282
458
 
283
- ## 🛠️ API Reference
459
+ ### Con WuMixin
284
460
 
285
- ### Core API
461
+ ```js
462
+ import { LitElement, html } from 'lit';
463
+ import { WuMixin } from 'wu-framework/adapters/lit';
464
+
465
+ class MyApp extends WuMixin(LitElement) {
466
+ connectedCallback() {
467
+ super.connectedCallback();
468
+
469
+ // Usar eventos de Wu
470
+ this.wuOn('user:login', (data) => {
471
+ console.log('User logged in:', data);
472
+ });
473
+ }
474
+
475
+ handleClick() {
476
+ this.wuEmit('button:clicked', { id: 'my-button' });
477
+ }
478
+
479
+ render() {
480
+ return html`
481
+ <button @click=${this.handleClick}>Click me</button>
482
+ `;
483
+ }
484
+ }
485
+
486
+ wuLit.register('my-app', MyApp);
487
+ ```
488
+
489
+ ### Web Component Vanilla (sin Lit)
286
490
 
287
491
  ```js
288
- import { wu } from 'wu-framework';
492
+ import { wuLit } from 'wu-framework/adapters/lit';
493
+
494
+ class MyComponent extends HTMLElement {
495
+ connectedCallback() {
496
+ this.attachShadow({ mode: 'open' });
497
+ this.shadowRoot.innerHTML = '<h1>Hello Web Component!</h1>';
498
+ }
499
+ }
289
500
 
290
- // Inicializar framework
291
- await wu.init({ apps: [...] });
501
+ wuLit.registerWebComponent('my-component', MyComponent);
502
+ ```
503
+
504
+ ---
292
505
 
293
- // Montar app
294
- await wu.mount('appName', '#container');
506
+ ## 📦 Vanilla JS Adapter
295
507
 
296
- // Desmontar app
297
- await wu.unmount('appName');
508
+ ### Registro con Objeto
298
509
 
299
- // Definir lifecycle
300
- wu.define('appName', { mount, unmount });
510
+ ```js
511
+ import { wuVanilla } from 'wu-framework/adapters/vanilla';
301
512
 
302
- // Usar componente compartido
303
- const Component = await wu.use('app.Component');
513
+ wuVanilla.register('my-app', {
514
+ state: { count: 0 },
304
515
 
305
- // Obtener información
306
- const info = wu.getAppInfo('appName');
307
- const stats = wu.getStats();
516
+ render: (container, state) => {
517
+ container.innerHTML = `
518
+ <div>
519
+ <h1>Count: ${state.count}</h1>
520
+ <button id="increment">+</button>
521
+ </div>
522
+ `;
523
+ container.querySelector('#increment').onclick = () => {
524
+ state.count++;
525
+ // Re-render manual
526
+ };
527
+ },
308
528
 
309
- // Limpiar framework
310
- await wu.destroy();
529
+ destroy: (container) => {
530
+ container.innerHTML = '';
531
+ }
532
+ });
311
533
  ```
312
534
 
313
- ### Utils API
535
+ ### Registro con Clase
314
536
 
315
537
  ```js
316
- import { init, mount, define, use } from 'wu-framework';
538
+ import { wuVanilla } from 'wu-framework/adapters/vanilla';
317
539
 
318
- // API de conveniencia
319
- await init([{ name: 'app', url: 'http://localhost:3000' }]);
320
- await mount('app', '#container');
321
- define('app', { mount, unmount });
322
- const Component = await use('shared.Button');
540
+ class TodoApp {
541
+ constructor(container) {
542
+ this.container = container;
543
+ this.todos = [];
544
+ }
545
+
546
+ render() {
547
+ this.container.innerHTML = `
548
+ <ul>
549
+ ${this.todos.map(t => `<li>${t}</li>`).join('')}
550
+ </ul>
551
+ <input type="text" id="input" />
552
+ <button id="add">Add</button>
553
+ `;
554
+
555
+ this.container.querySelector('#add').onclick = () => {
556
+ const input = this.container.querySelector('#input');
557
+ this.todos.push(input.value);
558
+ this.render();
559
+ };
560
+ }
561
+
562
+ destroy() {
563
+ this.container.innerHTML = '';
564
+ }
565
+ }
566
+
567
+ wuVanilla.registerClass('todo-app', TodoApp);
323
568
  ```
324
569
 
325
- ### Development API
570
+ ### Registro con Template
326
571
 
327
572
  ```js
328
- import { dev } from 'wu-framework';
573
+ import { wuVanilla } from 'wu-framework/adapters/vanilla';
329
574
 
330
- // Debugging
331
- dev.enableDebug();
332
- dev.inspect();
575
+ wuVanilla.registerTemplate('header', `
576
+ <header>
577
+ <h1>My Header</h1>
578
+ <nav>
579
+ <a href="/">Home</a>
580
+ <a href="/about">About</a>
581
+ </nav>
582
+ </header>
583
+ `);
584
+
585
+ // Template dinámico
586
+ wuVanilla.registerTemplate('greeting',
587
+ (data) => `<h1>Hello, ${data.name}!</h1>`,
588
+ { data: { name: 'World' } }
589
+ );
590
+ ```
591
+
592
+ ### Componente Reactivo
593
+
594
+ ```js
595
+ import { wuVanilla } from 'wu-framework/adapters/vanilla';
596
+
597
+ const Counter = wuVanilla.createComponent({
598
+ state: { count: 0 },
599
+
600
+ template: (state) => `
601
+ <div>
602
+ <h1>Count: ${state.count}</h1>
603
+ <button data-action="increment">+</button>
604
+ <button data-action="decrement">-</button>
605
+ </div>
606
+ `,
607
+
608
+ actions: {
609
+ increment: (state) => ({ count: state.count + 1 }),
610
+ decrement: (state) => ({ count: state.count - 1 })
611
+ }
612
+ });
333
613
 
334
- // Hot reload (desarrollo)
335
- await dev.reload('appName');
614
+ wuVanilla.register('counter', Counter);
336
615
  ```
337
616
 
338
- ## 🔧 Configuración Avanzada
617
+ ---
618
+
619
+ ## 📡 Event Bus
339
620
 
340
- ### Presets
621
+ Sistema de eventos para comunicación entre microfrontends con soporte para wildcards y replay.
341
622
 
342
623
  ```js
343
- import { wu, presets } from 'wu-framework';
624
+ import { emit, on, once, off, replayEvents } from 'wu-framework';
625
+
626
+ // Emitir evento
627
+ emit('user:login', { userId: 123, name: 'John' });
628
+
629
+ // Suscribirse a evento
630
+ const unsubscribe = on('user:login', (event) => {
631
+ console.log('User logged in:', event.data);
632
+ });
633
+
634
+ // Suscribirse con wildcards
635
+ on('user:*', (event) => {
636
+ console.log('User event:', event.name, event.data);
637
+ });
638
+
639
+ // Suscribirse una sola vez
640
+ once('app:ready', (event) => {
641
+ console.log('App is ready!');
642
+ });
344
643
 
345
- // Desarrollo
346
- await wu.init(presets.development([
347
- { name: 'header', port: 3001 },
348
- { name: 'sidebar', port: 3002 }
349
- ]));
644
+ // Desuscribirse
645
+ off('user:login', callback);
646
+ unsubscribe(); // También funciona
350
647
 
351
- // Producción
352
- await wu.init(presets.production([
353
- { name: 'header', url: 'https://header.myapp.com' },
354
- { name: 'sidebar', url: 'https://sidebar.myapp.com' }
355
- ]));
648
+ // Replay eventos del historial
649
+ replayEvents('user:*', (event) => {
650
+ console.log('Past event:', event);
651
+ });
356
652
  ```
357
653
 
358
- ### Eventos
654
+ ---
655
+
656
+ ## 🗄️ Store (State Management)
657
+
658
+ Store de alto rendimiento con pattern matching.
359
659
 
360
660
  ```js
361
- import { events } from 'wu-framework';
661
+ import {
662
+ getState,
663
+ setState,
664
+ onStateChange,
665
+ batchState,
666
+ clearState,
667
+ getStoreMetrics
668
+ } from 'wu-framework';
669
+
670
+ // Establecer estado (dot notation)
671
+ setState('user.name', 'John');
672
+ setState('user.preferences.theme', 'dark');
673
+
674
+ // Obtener estado
675
+ const name = getState('user.name'); // 'John'
676
+ const user = getState('user'); // { name: 'John', preferences: { theme: 'dark' } }
677
+
678
+ // Suscribirse a cambios
679
+ const unsubscribe = onStateChange('user.name', (value, path) => {
680
+ console.log(`${path} changed to:`, value);
681
+ });
362
682
 
363
- // Escuchar eventos del ciclo de vida
364
- events.onAppMounted((event) => {
365
- console.log('App mounted:', event.detail.appName);
683
+ // Suscribirse con wildcards
684
+ onStateChange('user.*', (value, path) => {
685
+ console.log(`User property changed: ${path} =`, value);
366
686
  });
367
687
 
368
- events.onAppError((event) => {
369
- console.error('App error:', event.detail);
688
+ // Batch updates (más eficiente)
689
+ batchState({
690
+ 'user.name': 'Jane',
691
+ 'user.email': 'jane@example.com',
692
+ 'settings.notifications': true
370
693
  });
694
+
695
+ // Métricas de performance
696
+ const metrics = getStoreMetrics();
371
697
  ```
372
698
 
373
- ## 🌟 Ventajas Competitivas
699
+ ---
374
700
 
375
- ### vs Module Federation
701
+ ## 🔌 Sistema de Plugins
376
702
 
377
- - ✅ **No requiere Webpack 5** - Funciona con cualquier bundler
378
- - **Runtime configuration** - No necesita build-time config
379
- - ✅ **Framework agnostic real** - No solo React
380
- - ✅ **API más simple** - Menos boilerplate
703
+ ```js
704
+ import { usePlugin, createPlugin, uninstallPlugin } from 'wu-framework';
381
705
 
382
- ### vs qiankun
706
+ const analyticsPlugin = createPlugin({
707
+ name: 'analytics',
708
+ permissions: ['events', 'store'],
383
709
 
384
- - **Shadow DOM nativo** - No hacks CSS
385
- - **Mejor DX** - DevTools integration
386
- - ✅ **Sandbox más ligero** - Menos overhead
387
- - ✅ **Component sharing** - Sistema declarativo
710
+ install: (api, options) => {
711
+ api.on('app:mounted', (event) => {
712
+ trackEvent('mount', event.data.appName);
713
+ });
714
+ },
388
715
 
389
- ### vs single-spa
716
+ beforeMount: async (context) => {
717
+ console.log('Before mount:', context.appName);
718
+ },
390
719
 
391
- - **Zero config** - Sin setup complejo
392
- - **Shadow DOM** - Aislamiento real
393
- - ✅ **Manifest system** - Configuración declarativa
394
- - ✅ **API moderna** - ES modules nativo
720
+ afterMount: async (context) => {
721
+ console.log('Mounted in', context.mountTime, 'ms');
722
+ }
723
+ });
395
724
 
396
- ## 📦 Bundler Support
725
+ usePlugin(analyticsPlugin, { trackingId: 'UA-123456' });
726
+ ```
397
727
 
398
- Wu Framework funciona con **cualquier bundler** o sin bundler:
728
+ ---
399
729
 
400
- ### Vite
730
+ ## 🪝 Lifecycle Hooks
401
731
 
402
732
  ```js
403
- // vite.config.js
404
- export default {
405
- // Wu Framework funciona out-of-the-box con Vite
406
- // No necesita configuración especial
407
- }
733
+ import { useHook, createGuardHook, createTimedHook } from 'wu-framework';
734
+
735
+ // Hook básico
736
+ useHook('beforeMount', async (context, next) => {
737
+ console.log('Before mounting:', context.appName);
738
+ await next();
739
+ }, { name: 'my-hook', priority: 10 });
740
+
741
+ // Guard hook (puede cancelar)
742
+ const authGuard = createGuardHook(async (ctx) => {
743
+ return await isUserAuthenticated();
744
+ });
745
+ useHook('beforeMount', authGuard);
746
+
747
+ // Hook con timeout
748
+ const timedHook = createTimedHook(async (ctx) => {
749
+ await slowOperation();
750
+ }, 5000);
408
751
  ```
409
752
 
410
- ### Webpack
753
+ ### Fases Disponibles
754
+
755
+ | Fase | Descripción |
756
+ |------|-------------|
757
+ | `beforeInit` | Antes de inicializar framework |
758
+ | `afterInit` | Después de inicializar |
759
+ | `beforeLoad` | Antes de cargar una app |
760
+ | `afterLoad` | Después de cargar |
761
+ | `beforeMount` | Antes de montar |
762
+ | `afterMount` | Después de montar |
763
+ | `beforeUnmount` | Antes de desmontar |
764
+ | `afterUnmount` | Después de desmontar |
765
+
766
+ ---
767
+
768
+ ## 🎯 Loading Strategies
411
769
 
412
770
  ```js
413
- // webpack.config.js
414
- module.exports = {
415
- // Wu Framework funciona con cualquier versión de Webpack
416
- // Sin plugins especiales requeridos
417
- }
771
+ await wu.init({
772
+ apps: [
773
+ { name: 'header', url: '...', strategy: 'lazy' }, // Default
774
+ { name: 'sidebar', url: '...', strategy: 'eager' }, // Precarga
775
+ { name: 'footer', url: '...', strategy: 'preload' }, // <link prefetch>
776
+ { name: 'analytics', url: '...', strategy: 'idle' } // requestIdleCallback
777
+ ]
778
+ });
418
779
  ```
419
780
 
420
- ### Sin Bundler (ES Modules)
781
+ ---
421
782
 
422
- ```html
423
- <!-- Funciona directamente en el browser -->
424
- <script type="module">
425
- import { wu } from './node_modules/wu-framework/src/index.js';
783
+ ## ⚡ Performance Monitoring
426
784
 
427
- wu.init({
428
- apps: [{ name: 'app', url: './my-app' }]
429
- });
430
- </script>
785
+ ```js
786
+ import {
787
+ startMeasure,
788
+ endMeasure,
789
+ getPerformanceMetrics,
790
+ generatePerformanceReport
791
+ } from 'wu-framework';
792
+
793
+ // Medición personalizada
794
+ startMeasure('data-fetch', 'my-app');
795
+ await fetchData();
796
+ const duration = endMeasure('data-fetch', 'my-app');
797
+
798
+ // Reporte completo
799
+ const report = generatePerformanceReport();
431
800
  ```
432
801
 
433
- ## 🚀 Getting Started
802
+ ---
434
803
 
435
- ### 1. Crear Container App
804
+ ## 🛡️ Error Handling
436
805
 
437
- ```bash
438
- mkdir my-container-app
439
- cd my-container-app
440
- npm init -y
441
- npm install wu-framework
806
+ ```js
807
+ import { registerErrorHandler, configureErrorBoundary } from 'wu-framework';
808
+
809
+ registerErrorHandler({
810
+ name: 'api-error',
811
+ canHandle: (error) => error.message.includes('API'),
812
+ handle: async (error, context) => {
813
+ if (context.retryCount < 3) {
814
+ return { recovered: true, action: 'retry' };
815
+ }
816
+ return { recovered: false, action: 'fallback' };
817
+ }
818
+ });
819
+
820
+ configureErrorBoundary({
821
+ maxRetries: 3,
822
+ retryDelay: 1000,
823
+ showErrorUI: true
824
+ });
442
825
  ```
443
826
 
827
+ ---
828
+
829
+ ## 🎯 API Simplificada (wu.app)
830
+
444
831
  ```js
445
- // index.js
446
832
  import { wu } from 'wu-framework';
447
833
 
448
- wu.init({
449
- apps: [
450
- { name: 'header', url: 'http://localhost:3001' },
451
- { name: 'content', url: 'http://localhost:3002' }
452
- ]
834
+ const header = wu.app('header', {
835
+ url: 'http://localhost:3001',
836
+ container: '#header-container'
453
837
  });
454
838
 
455
- wu.mount('header', '#header');
456
- wu.mount('content', '#content');
839
+ await header.mount();
840
+ console.log(header.isMounted); // true
841
+
842
+ await header.unmount();
843
+ await header.remount();
844
+ await header.reload(); // Limpia cache
845
+
846
+ const health = await header.verify();
847
+ await header.destroy();
457
848
  ```
458
849
 
459
- ```html
460
- <!-- index.html -->
461
- <!DOCTYPE html>
462
- <html>
463
- <head>
464
- <title>Wu Framework Container</title>
465
- </head>
466
- <body>
467
- <div id="header"></div>
468
- <div id="content"></div>
850
+ ---
851
+
852
+ ## 🏗️ Arquitectura
469
853
 
470
- <script type="module" src="index.js"></script>
471
- </body>
472
- </html>
854
+ ```
855
+ ┌─────────────────────────────────────────────────────────────┐
856
+ │ HOST APPLICATION │
857
+ ├─────────────────────────────────────────────────────────────┤
858
+ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
859
+ │ │ #shadow-root │ │ #shadow-root │ │ #shadow-root│ │
860
+ │ │ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌─────────┐ │ │
861
+ │ │ │ Header │ │ │ │ Sidebar │ │ │ │ Content │ │ │
862
+ │ │ │ (React) │ │ │ │ (Vue) │ │ │ │(Angular)│ │ │
863
+ │ │ └───────────┘ │ │ └───────────┘ │ │ └─────────┘ │ │
864
+ │ │ CSS Isolated │ │ CSS Isolated │ │ CSS Isolated│ │
865
+ │ │ JS Sandboxed │ │ JS Sandboxed │ │ JS Sandboxed│ │
866
+ │ └─────────────────┘ └─────────────────┘ └─────────────┘ │
867
+ ├─────────────────────────────────────────────────────────────┤
868
+ │ WU FRAMEWORK CORE │
869
+ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │
870
+ │ │ EventBus │ │ Store │ │ Plugins │ │ Sandbox Pool │ │
871
+ │ └──────────┘ └──────────┘ └──────────┘ └────────────────┘ │
872
+ └─────────────────────────────────────────────────────────────┘
473
873
  ```
474
874
 
475
- ### 2. Crear Micro App
875
+ ---
476
876
 
477
- ```bash
478
- mkdir header-app
479
- cd header-app
480
- npm init -y
481
- npm install wu-framework react react-dom
877
+ ## 📋 API Reference
878
+
879
+ ### Core
880
+
881
+ ```js
882
+ import { wu, init, mount, unmount, destroy, getStats } from 'wu-framework';
482
883
  ```
483
884
 
885
+ ### Event Bus
886
+
484
887
  ```js
485
- // index.js
486
- import React from 'react';
487
- import ReactDOM from 'react-dom';
488
- import { wu } from 'wu-framework';
888
+ import { emit, on, once, off, replayEvents, getEventBusStats } from 'wu-framework';
889
+ ```
489
890
 
490
- const HeaderApp = () => (
491
- <header style={{ background: '#f0f0f0', padding: '1rem' }}>
492
- <h1>My Header App</h1>
493
- </header>
494
- );
891
+ ### Store
495
892
 
496
- wu.define('header', {
497
- mount: (container) => {
498
- ReactDOM.render(<HeaderApp />, container);
499
- },
500
- unmount: (container) => {
501
- ReactDOM.unmountComponentAtNode(container);
502
- }
503
- });
893
+ ```js
894
+ import { getState, setState, onStateChange, batchState, clearState } from 'wu-framework';
504
895
  ```
505
896
 
506
- ```json
507
- // wu.json
508
- {
509
- "name": "header-app",
510
- "entry": "index.js",
511
- "wu": {
512
- "exports": {
513
- "HeaderComponent": "./components/Header"
514
- },
515
- "imports": [],
516
- "routes": ["/header"]
517
- }
518
- }
897
+ ### Plugins & Hooks
898
+
899
+ ```js
900
+ import { usePlugin, createPlugin, useHook, removeHook } from 'wu-framework';
519
901
  ```
520
902
 
521
- ### 3. Servir Apps
903
+ ### Performance & Errors
522
904
 
523
- ```bash
524
- # Terminal 1 - Container
525
- cd my-container-app
526
- npx serve -p 3000
905
+ ```js
906
+ import { startMeasure, endMeasure, generatePerformanceReport } from 'wu-framework';
907
+ import { registerErrorHandler, configureErrorBoundary } from 'wu-framework';
908
+ ```
527
909
 
528
- # Terminal 2 - Header App
529
- cd header-app
530
- npx serve -p 3001
910
+ ### Adapters
531
911
 
532
- # Abrir http://localhost:3000
912
+ ```js
913
+ import { wuReact } from 'wu-framework/adapters/react';
914
+ import { wuVue } from 'wu-framework/adapters/vue';
915
+ import { wuAngular } from 'wu-framework/adapters/angular';
916
+ import { wuSvelte } from 'wu-framework/adapters/svelte';
917
+ import { wuPreact } from 'wu-framework/adapters/preact';
918
+ import { wuSolid } from 'wu-framework/adapters/solid';
919
+ import { wuLit } from 'wu-framework/adapters/lit';
920
+ import { wuVanilla } from 'wu-framework/adapters/vanilla';
533
921
  ```
534
922
 
535
- ## 🤝 Contributing
923
+ ### Utilities
536
924
 
537
- Wu Framework es open source. ¡Contribuciones bienvenidas!
925
+ ```js
926
+ import { presets, dev, events } from 'wu-framework';
538
927
 
539
- 1. Fork el repositorio
540
- 2. Crear feature branch (`git checkout -b feature/amazing-feature`)
541
- 3. Commit cambios (`git commit -m 'Add amazing feature'`)
542
- 4. Push branch (`git push origin feature/amazing-feature`)
543
- 5. Abrir Pull Request
928
+ // Presets
929
+ await wu.init(presets.development([{ name: 'app', port: 3001 }]));
930
+ await wu.init(presets.production([{ name: 'app', url: 'https://...' }]));
544
931
 
545
- ## 📄 License
932
+ // Dev tools
933
+ dev.enableDebug();
934
+ dev.inspect();
935
+ await dev.reload('app');
936
+
937
+ // Silenciar logs
938
+ wu.silence();
939
+ wu.verbose();
940
+ ```
941
+
942
+ ---
546
943
 
547
- MIT License - ver [LICENSE](LICENSE) para detalles.
944
+ ## 🤝 Contributing
548
945
 
549
- ## 🙏 Acknowledgments
946
+ ¡Las contribuciones son bienvenidas!
550
947
 
551
- - Inspirado por qiankun, single-spa, y Module Federation
552
- - Construido con amor para la comunidad de microfrontends
553
- - Gracias a todos los contributors
948
+ 1. **Fork** el repositorio
949
+ 2. **Crear** branch (`git checkout -b feature/amazing-feature`)
950
+ 3. **Commit** tus cambios (`git commit -m 'Add amazing feature'`)
951
+ 4. **Push** al branch (`git push origin feature/amazing-feature`)
952
+ 5. **Abrir** un Pull Request
554
953
 
555
954
  ---
556
955
 
557
- **🚀 Wu Framework - Universal Microfrontends Made Simple**
956
+ ## 📄 License
957
+
958
+ MIT License - Copyright (c) 2025 Wu Framework Team
959
+
960
+ ---
558
961
 
559
- *Framework agnostic • Zero config • Shadow DOM • Runtime loading*
962
+ <p align="center">
963
+ <b>🚀 Wu Framework - Universal Microfrontends Made Simple</b>
964
+ <br><br>
965
+ <i>Zero dependencies • 8 Frameworks • Shadow DOM • Proxy Sandbox • Self-Healing</i>
966
+ </p>