wu-framework 1.1.7 → 1.1.9
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/LICENSE +19 -1
- package/README.md +257 -1122
- package/dist/wu-framework.cjs.js +3 -1
- package/dist/wu-framework.cjs.js.map +1 -0
- package/dist/wu-framework.dev.js +9867 -3183
- package/dist/wu-framework.dev.js.map +1 -1
- package/dist/wu-framework.esm.js +3 -0
- package/dist/wu-framework.esm.js.map +1 -0
- package/dist/wu-framework.umd.js +3 -1
- package/dist/wu-framework.umd.js.map +1 -0
- package/integrations/astro/README.md +127 -0
- package/integrations/astro/WuApp.astro +63 -0
- package/integrations/astro/WuShell.astro +39 -0
- package/integrations/astro/index.js +68 -0
- package/integrations/astro/package.json +38 -0
- package/integrations/astro/types.d.ts +53 -0
- package/package.json +96 -72
- package/src/adapters/angular/ai.js +30 -0
- package/src/adapters/angular/index.d.ts +154 -0
- package/src/adapters/angular/index.js +932 -0
- package/src/adapters/angular.d.ts +3 -154
- package/src/adapters/angular.js +3 -813
- package/src/adapters/index.js +35 -24
- package/src/adapters/lit/ai.js +20 -0
- package/src/adapters/lit/index.d.ts +120 -0
- package/src/adapters/lit/index.js +721 -0
- package/src/adapters/lit.d.ts +3 -120
- package/src/adapters/lit.js +3 -726
- package/src/adapters/preact/ai.js +33 -0
- package/src/adapters/preact/index.d.ts +108 -0
- package/src/adapters/preact/index.js +661 -0
- package/src/adapters/preact.d.ts +3 -108
- package/src/adapters/preact.js +3 -665
- package/src/adapters/react/ai.js +135 -0
- package/src/adapters/react/index.d.ts +246 -0
- package/src/adapters/react/index.js +694 -0
- package/src/adapters/react.d.ts +3 -212
- package/src/adapters/react.js +3 -513
- package/src/adapters/shared.js +64 -0
- package/src/adapters/solid/ai.js +32 -0
- package/src/adapters/solid/index.d.ts +101 -0
- package/src/adapters/solid/index.js +586 -0
- package/src/adapters/solid.d.ts +3 -101
- package/src/adapters/solid.js +3 -591
- package/src/adapters/svelte/ai.js +31 -0
- package/src/adapters/svelte/index.d.ts +166 -0
- package/src/adapters/svelte/index.js +798 -0
- package/src/adapters/svelte.d.ts +3 -166
- package/src/adapters/svelte.js +3 -803
- package/src/adapters/vanilla/ai.js +30 -0
- package/src/adapters/vanilla/index.d.ts +179 -0
- package/src/adapters/vanilla/index.js +785 -0
- package/src/adapters/vanilla.d.ts +3 -179
- package/src/adapters/vanilla.js +3 -791
- package/src/adapters/vue/ai.js +52 -0
- package/src/adapters/vue/index.d.ts +299 -0
- package/src/adapters/vue/index.js +608 -0
- package/src/adapters/vue.d.ts +3 -299
- package/src/adapters/vue.js +3 -611
- package/src/ai/wu-ai-actions.js +261 -0
- package/src/ai/wu-ai-agent.js +546 -0
- package/src/ai/wu-ai-browser-primitives.js +354 -0
- package/src/ai/wu-ai-browser.js +380 -0
- package/src/ai/wu-ai-context.js +332 -0
- package/src/ai/wu-ai-conversation.js +613 -0
- package/src/ai/wu-ai-orchestrate.js +1021 -0
- package/src/ai/wu-ai-permissions.js +381 -0
- package/src/ai/wu-ai-provider.js +700 -0
- package/src/ai/wu-ai-schema.js +225 -0
- package/src/ai/wu-ai-triggers.js +396 -0
- package/src/ai/wu-ai.js +804 -0
- package/src/core/wu-app.js +50 -8
- package/src/core/wu-cache.js +2 -3
- package/src/core/wu-core.js +648 -681
- package/src/core/wu-html-parser.js +121 -211
- package/src/core/wu-iframe-sandbox.js +328 -0
- package/src/core/wu-mcp-bridge.js +431 -0
- package/src/core/wu-overrides.js +510 -0
- package/src/core/wu-plugin.js +4 -1
- package/src/core/wu-prefetch.js +414 -0
- package/src/core/wu-proxy-sandbox.js +398 -75
- package/src/core/wu-sandbox.js +86 -268
- package/src/core/wu-script-executor.js +79 -182
- package/src/core/wu-snapshot-sandbox.js +149 -106
- package/src/core/wu-strategies.js +13 -0
- package/src/core/wu-style-bridge.js +23 -23
- package/src/index.js +162 -665
- package/dist/wu-framework.hex.js +0 -23
- package/dist/wu-framework.min.js +0 -1
- package/dist/wu-framework.obf.js +0 -1
- package/scripts/build-protected.js +0 -366
- package/scripts/build.js +0 -212
- package/scripts/rollup-plugin-hex.js +0 -143
- package/src/core/wu-registry.js +0 -60
- package/src/core/wu-sandbox-pool.js +0 -390
package/README.md
CHANGED
|
@@ -1,1273 +1,408 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://wu-framework.dev/favicon.svg" width="80" alt="Wu Framework" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Wu Framework</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Universal microfrontends with built-in AI. Zero dependencies.</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/wu-framework"><img src="https://img.shields.io/npm/v/wu-framework.svg?color=8b5cf6&label=npm" alt="npm version" /></a>
|
|
13
|
+
<a href="https://github.com/wu-framework/wu-framework/actions"><img src="https://img.shields.io/github/actions/workflow/status/wu-framework/wu-framework/ci.yml?label=tests&color=10b981" alt="tests" /></a>
|
|
14
|
+
<img src="https://img.shields.io/badge/tests-650%20passed-10b981" alt="650 tests" />
|
|
15
|
+
<img src="https://img.shields.io/badge/dependencies-0-8b5cf6" alt="zero deps" />
|
|
16
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License" /></a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="https://wu-framework.dev">Documentation</a> ·
|
|
21
|
+
<a href="https://wu-framework.dev/docs/quick-start">Quick Start</a> ·
|
|
22
|
+
<a href="https://wu-framework.dev/docs/ai/overview">AI Integration</a> ·
|
|
23
|
+
<a href="#wucommerce--real-world-example">Live Example</a>
|
|
24
|
+
</p>
|
|
2
25
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Wu Framework es la libreria de microfrontends mas simple y poderosa del mercado. Framework agnostic, zero config, Shadow DOM nativo.
|
|
6
|
-
|
|
7
|
-
## Por que Wu Framework?
|
|
26
|
+
---
|
|
8
27
|
|
|
9
|
-
|
|
10
|
-
|---|---|---|---|---|
|
|
11
|
-
| **Setup** | Webpack config complejo | Configuracion manual | Config extensa | **Zero config** |
|
|
12
|
-
| **Framework Support** | React-first | Multi framework | Multi framework | **8 frameworks nativos** |
|
|
13
|
-
| **Bundler Required** | Solo Webpack 5 | Agnostico | Agnostico | **Ninguno requerido** |
|
|
14
|
-
| **CSS Isolation** | Basico | CSS hacks | Manual | **Shadow DOM nativo** |
|
|
15
|
-
| **JS Isolation** | No | Proxy basico | No | **Proxy + Snapshot Sandbox** |
|
|
16
|
-
| **Style Modes** | No | No | No | **3 modos (shared/isolated/fully-isolated)** |
|
|
17
|
-
| **Runtime Config** | No | Limitado | Limitado | **Completamente dinamico** |
|
|
18
|
-
| **Self-Healing** | No | No | No | **Auto-recovery** |
|
|
19
|
-
| **Build Protection** | No | No | No | **Minify + Obfuscate + Base64** |
|
|
20
|
-
| **API Complexity** | Alta | Media | Alta | **1 linea de codigo** |
|
|
28
|
+
Run **React, Vue, Angular, Svelte, Solid, Preact, Lit, and Vanilla JS** micro-apps side by side in the same page. Each app lives in its own Shadow DOM with full CSS isolation. Apps communicate through a shared event bus and store — no tight coupling, no iframes.
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
Add AI to any app with one line. Connect your own LLM (OpenAI, Anthropic, Ollama) and your app gains context-aware tool calling, autonomous agents, and cross-app orchestration. **WebMCP ready** for Chrome 146+.
|
|
23
31
|
|
|
24
32
|
```bash
|
|
25
33
|
npm install wu-framework
|
|
26
34
|
```
|
|
27
35
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## Frameworks Soportados
|
|
33
|
-
|
|
34
|
-
Wu Framework incluye **adapters nativos** para los frameworks mas populares:
|
|
35
|
-
|
|
36
|
-
| Framework | Adapter | Registro |
|
|
37
|
-
|-----------|---------|----------|
|
|
38
|
-
| React | `wuReact` | `wuReact.register('app', App)` |
|
|
39
|
-
| Vue | `wuVue` | `wuVue.register('app', App)` |
|
|
40
|
-
| Angular | `wuAngular` | `wuAngular.register('app', AppModule)` |
|
|
41
|
-
| Angular Standalone | `wuAngular` | `wuAngular.registerStandalone('app', Component)` |
|
|
42
|
-
| Angular Elements | `wuAngular` | `wuAngular.registerElement('app', Component)` |
|
|
43
|
-
| Svelte | `wuSvelte` | `wuSvelte.register('app', App)` |
|
|
44
|
-
| Preact | `wuPreact` | `wuPreact.register('app', App)` |
|
|
45
|
-
| Solid.js | `wuSolid` | `wuSolid.register('app', App)` |
|
|
46
|
-
| Lit | `wuLit` | `wuLit.register('app', MyElement)` |
|
|
47
|
-
| Vanilla JS | `wuVanilla` | `wuVanilla.register('app', config)` |
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## Quick Start
|
|
36
|
+
## 30-Second Demo
|
|
52
37
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Cada microfrontend necesita un archivo `wu.json` en su raiz:
|
|
56
|
-
|
|
57
|
-
```json
|
|
58
|
-
{
|
|
59
|
-
"name": "header",
|
|
60
|
-
"version": "1.0.0",
|
|
61
|
-
"entry": "index.js",
|
|
62
|
-
"styleMode": "shared",
|
|
63
|
-
"wu": {
|
|
64
|
-
"exports": {
|
|
65
|
-
"NavBar": "components/NavBar.js",
|
|
66
|
-
"UserMenu": "components/UserMenu.js"
|
|
67
|
-
},
|
|
68
|
-
"imports": [],
|
|
69
|
-
"routes": ["/", "/home"],
|
|
70
|
-
"permissions": ["events", "store"]
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
| Campo | Descripcion |
|
|
76
|
-
|-------|-------------|
|
|
77
|
-
| `name` | Nombre unico del microfrontend |
|
|
78
|
-
| `version` | Version del microfrontend |
|
|
79
|
-
| `entry` | Archivo JS principal (default: `index.js`) |
|
|
80
|
-
| `styleMode` | Modo de estilos: `shared`, `isolated`, `fully-isolated` |
|
|
81
|
-
| `wu.exports` | Componentes que expone a otros microfrontends |
|
|
82
|
-
| `wu.imports` | Componentes que importa de otros microfrontends |
|
|
83
|
-
| `wu.routes` | Rutas que maneja este microfrontend |
|
|
84
|
-
| `wu.permissions` | Permisos requeridos (`events`, `store`, `dom`) |
|
|
85
|
-
|
|
86
|
-
### 2. Micro App: Registrar con Adapter (1 linea)
|
|
87
|
-
|
|
88
|
-
**React:**
|
|
89
|
-
```tsx
|
|
38
|
+
```js
|
|
39
|
+
import { wu } from 'wu-framework';
|
|
90
40
|
import { wuReact } from 'wu-framework/adapters/react';
|
|
91
|
-
import App from './App';
|
|
92
|
-
|
|
93
|
-
wuReact.register('header', App);
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
**Vue:**
|
|
97
|
-
```ts
|
|
98
41
|
import { wuVue } from 'wu-framework/adapters/vue';
|
|
99
|
-
import App from './App.vue';
|
|
100
42
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
**Angular:**
|
|
105
|
-
```ts
|
|
106
|
-
import { wuAngular } from 'wu-framework/adapters/angular';
|
|
107
|
-
import { AppModule } from './app/app.module';
|
|
43
|
+
// Register micro-apps from different frameworks
|
|
44
|
+
wuReact.register('cart', CartApp);
|
|
45
|
+
wuVue.register('catalog', CatalogApp);
|
|
108
46
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
El adapter se encarga de todo: deteccion de contexto, modo standalone, cleanup automatico.
|
|
47
|
+
// Mount them — each gets its own Shadow DOM
|
|
48
|
+
await wu.mount('cart', '#cart-container');
|
|
49
|
+
await wu.mount('catalog', '#catalog-container');
|
|
113
50
|
|
|
114
|
-
|
|
51
|
+
// They talk to each other via events
|
|
52
|
+
wu.emit('cart:item-added', { productId: 'SKU-42' });
|
|
53
|
+
wu.on('catalog:product-selected', (e) => console.log(e.data));
|
|
115
54
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
{ name: 'header', url: 'http://localhost:3001' },
|
|
123
|
-
{ name: 'sidebar', url: 'http://localhost:3002' },
|
|
124
|
-
{ name: 'content', url: 'http://localhost:3003' }
|
|
125
|
-
]
|
|
55
|
+
// Add AI with one line — BYOL (Bring Your Own LLM)
|
|
56
|
+
wu.ai.provider('openai', { endpoint: '/api/ai/chat', model: 'gpt-4o' });
|
|
57
|
+
wu.ai.action('addToCart', {
|
|
58
|
+
description: 'Add a product to the shopping cart',
|
|
59
|
+
parameters: { productId: { type: 'string', required: true } },
|
|
60
|
+
handler: async (params) => wu.emit('cart:item-added', params),
|
|
126
61
|
});
|
|
127
62
|
|
|
128
|
-
|
|
129
|
-
await wu.
|
|
130
|
-
await wu.mount('content', '#content-container');
|
|
63
|
+
// Now the AI can control your app
|
|
64
|
+
await wu.ai.send('Add product SKU-42 to the cart');
|
|
131
65
|
```
|
|
132
66
|
|
|
133
|
-
|
|
134
|
-
```js
|
|
135
|
-
import { wu } from 'wu-framework';
|
|
136
|
-
|
|
137
|
-
await wu.init({
|
|
138
|
-
apps: [
|
|
139
|
-
{ name: 'header', url: 'https://cdn.mycompany.com/mfe/header' },
|
|
140
|
-
{ name: 'sidebar', url: 'https://cdn.mycompany.com/mfe/sidebar' },
|
|
141
|
-
{ name: 'content', url: 'https://cdn.mycompany.com/mfe/content' }
|
|
142
|
-
]
|
|
143
|
-
});
|
|
144
|
-
```
|
|
67
|
+
## Why Wu?
|
|
145
68
|
|
|
146
|
-
|
|
69
|
+
| | **Wu Framework** | **single-spa** | **Module Federation** | **iframes** |
|
|
70
|
+
|---|:---:|:---:|:---:|:---:|
|
|
71
|
+
| Framework adapters | **8** | 4 | 1* | Any |
|
|
72
|
+
| Shadow DOM isolation | Yes | No | No | Yes (heavy) |
|
|
73
|
+
| Shared event bus | Built-in | Manual | Manual | postMessage |
|
|
74
|
+
| Shared store | Built-in | Manual | Manual | No |
|
|
75
|
+
| Standalone mode | Automatic | No | No | N/A |
|
|
76
|
+
| AI integration | Built-in | No | No | No |
|
|
77
|
+
| WebMCP (Chrome 146+) | Built-in | No | No | No |
|
|
78
|
+
| MCP Server (dev tools) | Built-in | No | No | No |
|
|
79
|
+
| Dependencies | **0** | 0 | Webpack 5 | N/A |
|
|
80
|
+
| Bundle size (min) | ~174 KB | ~10 KB | Varies | N/A |
|
|
147
81
|
|
|
148
|
-
|
|
149
|
-
my-header-mfe/
|
|
150
|
-
├── wu.json # Manifest requerido
|
|
151
|
-
├── index.js # Entry point (registra con adapter)
|
|
152
|
-
├── App.jsx # Componente principal
|
|
153
|
-
├── components/
|
|
154
|
-
│ ├── NavBar.js
|
|
155
|
-
│ └── UserMenu.js
|
|
156
|
-
└── package.json
|
|
157
|
-
```
|
|
82
|
+
*Module Federation is Webpack-coupled; Wu is bundler-agnostic.
|
|
158
83
|
|
|
159
84
|
---
|
|
160
85
|
|
|
161
|
-
##
|
|
162
|
-
|
|
163
|
-
Wu Framework soporta **3 modos de inyeccion de estilos** en Shadow DOM:
|
|
164
|
-
|
|
165
|
-
| Modo | Descripcion | Riesgo Colision |
|
|
166
|
-
|------|-------------|-----------------|
|
|
167
|
-
| `shared` | Inyecta TODOS los estilos del documento padre | Alto |
|
|
168
|
-
| `isolated` | NO inyecta estilos externos (Shadow DOM nativo) | Ninguno |
|
|
169
|
-
| `fully-isolated` | Inyecta SOLO estilos propios de la app | Ninguno |
|
|
170
|
-
|
|
171
|
-
### Configuracion en wu.json
|
|
172
|
-
|
|
173
|
-
```json
|
|
174
|
-
{
|
|
175
|
-
"name": "my-app",
|
|
176
|
-
"styleMode": "isolated"
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### shared (default)
|
|
181
|
-
|
|
182
|
-
- Inyecta estilos de librerias (Element Plus, Tailwind, Vue Flow, etc.)
|
|
183
|
-
- Inyecta estilos globales del documento
|
|
184
|
-
- Observer HMR para cambios en desarrollo
|
|
185
|
-
- **Ideal para:** Apps que comparten un design system comun
|
|
186
|
-
|
|
187
|
-
### isolated
|
|
86
|
+
## Features
|
|
188
87
|
|
|
189
|
-
|
|
190
|
-
- Usa encapsulamiento nativo del Shadow DOM
|
|
191
|
-
- La app debe incluir sus propios estilos (CSS-in-JS, scoped, imports)
|
|
192
|
-
- **Ideal para:** Apps con estilos completamente independientes
|
|
193
|
-
|
|
194
|
-
### fully-isolated
|
|
88
|
+
### Core
|
|
195
89
|
|
|
196
|
-
-
|
|
197
|
-
-
|
|
198
|
-
-
|
|
199
|
-
- **
|
|
90
|
+
- **8 Framework Adapters** — React, Vue, Angular, Svelte, Solid, Preact, Lit, Vanilla
|
|
91
|
+
- **Shadow DOM Isolation** — CSS and DOM fully sandboxed per app
|
|
92
|
+
- **3 Sandbox Strategies** — Shadow DOM, Proxy, iframe — choose per app
|
|
93
|
+
- **3 CSS Isolation Modes** — `shared`, `isolated`, `fully-isolated` per app
|
|
94
|
+
- **Event Bus** — Namespaced pub/sub with wildcards, replay, and middleware
|
|
95
|
+
- **Shared Store** — Cross-app reactive state with dot-path notation and persistence
|
|
96
|
+
- **Plugin System** — Extend Wu with lifecycle hooks
|
|
97
|
+
- **Performance Monitor** — Mount time, memory, FPS tracking per app
|
|
98
|
+
- **Error Boundaries** — Catch and recover from micro-app failures
|
|
99
|
+
- **Keep-Alive** — Preserve app state when hiding/showing
|
|
100
|
+
- **Prefetch** — Speculation Rules API with automatic fallback chain
|
|
101
|
+
- **Cookie Overrides** — QA redirects individual apps to different URLs per-browser
|
|
102
|
+
- **Standalone Mode** — Every micro-app works without a shell, zero lock-in
|
|
103
|
+
|
|
104
|
+
### AI (BYOL — Bring Your Own LLM)
|
|
105
|
+
|
|
106
|
+
- **4 Paradigms** — App→LLM, LLM→App, Autonomous Agent, Cross-App Orchestration
|
|
107
|
+
- **Tool Calling** — Register actions the AI executes autonomously
|
|
108
|
+
- **Streaming** — Async generator for real-time responses
|
|
109
|
+
- **Multi-turn** — Namespaced conversations with history
|
|
110
|
+
- **Reactive Triggers** — Events automatically invoke the AI
|
|
111
|
+
- **Auto Context** — Store state, apps, events injected into the system prompt
|
|
112
|
+
- **10 Browser Actions** — Screenshot, click, type, navigate, read console/network
|
|
113
|
+
- **WebMCP** — `wu.ai.expose()` registers tools via `navigator.modelContext` (Chrome 146+)
|
|
114
|
+
- **MCP Server** — Connect Claude Code, Cursor, or any MCP client to your live app
|
|
115
|
+
- **4-Layer Security** — Permissions, rate limiting, circuit breaker, loop protection
|
|
116
|
+
- **Workflows** — Reusable parameterized AI recipes
|
|
200
117
|
|
|
201
118
|
---
|
|
202
119
|
|
|
203
|
-
##
|
|
120
|
+
## Quick Start
|
|
204
121
|
|
|
205
|
-
###
|
|
122
|
+
### 1. Register your micro-app
|
|
206
123
|
|
|
207
|
-
```
|
|
124
|
+
```jsx
|
|
125
|
+
// React
|
|
208
126
|
import { wuReact } from 'wu-framework/adapters/react';
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
wuReact.register('my-app', App);
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### Con Opciones
|
|
215
|
-
|
|
216
|
-
```tsx
|
|
217
|
-
wuReact.register('my-app', App, {
|
|
218
|
-
strictMode: true, // Envolver en React.StrictMode
|
|
219
|
-
props: { theme: 'dark' }, // Props iniciales
|
|
220
|
-
standalone: true, // Ejecutar independiente si Wu no esta
|
|
221
|
-
standaloneContainer: '#root',
|
|
222
|
-
onMount: (container) => console.log('Mounted!'),
|
|
223
|
-
onUnmount: (container) => console.log('Unmounted!')
|
|
224
|
-
});
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### Hooks para React
|
|
127
|
+
wuReact.register('orders', App);
|
|
228
128
|
|
|
229
|
-
|
|
230
|
-
import React from 'react';
|
|
231
|
-
import { createUseWuEvents, createUseWuStore } from 'wu-framework/adapters/react';
|
|
232
|
-
|
|
233
|
-
const useWuEvents = createUseWuEvents(React);
|
|
234
|
-
const useWuStore = createUseWuStore(React);
|
|
235
|
-
|
|
236
|
-
function MyComponent() {
|
|
237
|
-
const { emit, on } = useWuEvents();
|
|
238
|
-
const { state, setState } = useWuStore('user');
|
|
239
|
-
|
|
240
|
-
useEffect(() => {
|
|
241
|
-
const unsub = on('cart:updated', (data) => {
|
|
242
|
-
console.log('Cart updated:', data);
|
|
243
|
-
});
|
|
244
|
-
return unsub;
|
|
245
|
-
}, [on]);
|
|
246
|
-
|
|
247
|
-
return (
|
|
248
|
-
<button onClick={() => emit('user:logout')}>
|
|
249
|
-
Logout {state?.name}
|
|
250
|
-
</button>
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### Cargar Microfrontends en React (Shell)
|
|
256
|
-
|
|
257
|
-
```tsx
|
|
258
|
-
import React from 'react';
|
|
259
|
-
import { createWuSlot } from 'wu-framework/adapters/react';
|
|
260
|
-
|
|
261
|
-
const WuSlot = createWuSlot(React);
|
|
262
|
-
|
|
263
|
-
const HEADER_URL = process.env.REACT_APP_HEADER_URL || 'http://localhost:3001';
|
|
264
|
-
|
|
265
|
-
function Shell() {
|
|
266
|
-
return (
|
|
267
|
-
<div>
|
|
268
|
-
<WuSlot
|
|
269
|
-
name="header"
|
|
270
|
-
url={HEADER_URL}
|
|
271
|
-
onLoad={() => console.log('Header loaded!')}
|
|
272
|
-
onError={(err) => console.error(err)}
|
|
273
|
-
/>
|
|
274
|
-
</div>
|
|
275
|
-
);
|
|
276
|
-
}
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
---
|
|
280
|
-
|
|
281
|
-
## Vue Adapter
|
|
282
|
-
|
|
283
|
-
### Registro Basico
|
|
284
|
-
|
|
285
|
-
```ts
|
|
129
|
+
// Vue
|
|
286
130
|
import { wuVue } from 'wu-framework/adapters/vue';
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
wuVue.register('my-app', App);
|
|
290
|
-
```
|
|
131
|
+
wuVue.register('products', App);
|
|
291
132
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
```ts
|
|
295
|
-
import { wuVue } from 'wu-framework/adapters/vue';
|
|
296
|
-
import { createPinia } from 'pinia';
|
|
297
|
-
import router from './router';
|
|
298
|
-
import App from './App.vue';
|
|
299
|
-
|
|
300
|
-
wuVue.register('my-app', App, {
|
|
301
|
-
setup: (app) => {
|
|
302
|
-
app.use(createPinia());
|
|
303
|
-
app.use(router);
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
### Composables para Vue
|
|
309
|
-
|
|
310
|
-
```vue
|
|
311
|
-
<script setup>
|
|
312
|
-
import { onMounted, onUnmounted } from 'vue';
|
|
313
|
-
import { useWuEvents, useWuStore } from 'wu-framework/adapters/vue';
|
|
314
|
-
|
|
315
|
-
const { emit, on, cleanup } = useWuEvents();
|
|
316
|
-
const { state, setState } = useWuStore('cart');
|
|
317
|
-
|
|
318
|
-
onMounted(() => {
|
|
319
|
-
on('user:login', (data) => console.log('Login:', data));
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
onUnmounted(() => cleanup());
|
|
323
|
-
</script>
|
|
324
|
-
|
|
325
|
-
<template>
|
|
326
|
-
<div>
|
|
327
|
-
<p>Items: {{ state?.items?.length }}</p>
|
|
328
|
-
<button @click="emit('cart:clear')">Clear Cart</button>
|
|
329
|
-
</div>
|
|
330
|
-
</template>
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### Cargar Microfrontends en Vue (Shell)
|
|
334
|
-
|
|
335
|
-
```vue
|
|
336
|
-
<script setup>
|
|
337
|
-
import { WuSlot } from 'wu-framework/adapters/vue';
|
|
338
|
-
|
|
339
|
-
const headerUrl = import.meta.env.VITE_HEADER_URL || 'http://localhost:3001';
|
|
340
|
-
</script>
|
|
341
|
-
|
|
342
|
-
<template>
|
|
343
|
-
<div>
|
|
344
|
-
<WuSlot
|
|
345
|
-
name="header"
|
|
346
|
-
:url="headerUrl"
|
|
347
|
-
@load="onLoad"
|
|
348
|
-
@error="onError"
|
|
349
|
-
/>
|
|
350
|
-
</div>
|
|
351
|
-
</template>
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
### Plugin Global
|
|
355
|
-
|
|
356
|
-
```ts
|
|
357
|
-
import { createApp } from 'vue';
|
|
358
|
-
import { wuVuePlugin } from 'wu-framework/adapters/vue';
|
|
359
|
-
|
|
360
|
-
const app = createApp(App);
|
|
361
|
-
app.use(wuVuePlugin); // Registra <WuSlot> globalmente
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
---
|
|
365
|
-
|
|
366
|
-
## Angular Adapter
|
|
367
|
-
|
|
368
|
-
### Registro con NgModule
|
|
369
|
-
|
|
370
|
-
```ts
|
|
133
|
+
// Angular (standalone)
|
|
371
134
|
import { wuAngular } from 'wu-framework/adapters/angular';
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
wuAngular.register('my-app', AppModule);
|
|
375
|
-
```
|
|
135
|
+
wuAngular.registerStandalone('settings', AppComponent, { createApplication, createComponent });
|
|
376
136
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
```ts
|
|
380
|
-
import { wuAngular } from 'wu-framework/adapters/angular';
|
|
381
|
-
import { AppComponent } from './app/app.component';
|
|
382
|
-
import { appConfig } from './app/app.config';
|
|
383
|
-
|
|
384
|
-
wuAngular.registerStandalone('my-app', AppComponent, {
|
|
385
|
-
appConfig
|
|
386
|
-
});
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
### Registro con Angular Elements (Web Components)
|
|
390
|
-
|
|
391
|
-
Para proyectos que usan Angular Elements para crear Web Components:
|
|
392
|
-
|
|
393
|
-
```ts
|
|
394
|
-
import { wuAngular } from 'wu-framework/adapters/angular';
|
|
395
|
-
import { AppComponent } from './app/app.component';
|
|
396
|
-
import { appConfig } from './app/app.config';
|
|
397
|
-
|
|
398
|
-
wuAngular.registerElement('my-app', AppComponent, {
|
|
399
|
-
elementTag: 'my-app-element', // Tag del custom element
|
|
400
|
-
appConfig, // Configuracion de Angular
|
|
401
|
-
standaloneContainer: '#root', // Container para modo standalone
|
|
402
|
-
onMount: (container, element) => {
|
|
403
|
-
console.log('Angular Element mounted');
|
|
404
|
-
},
|
|
405
|
-
onUnmount: (container, element) => {
|
|
406
|
-
console.log('Angular Element unmounted');
|
|
407
|
-
}
|
|
408
|
-
});
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
El adapter se encarga de:
|
|
412
|
-
- Crear la aplicacion Angular
|
|
413
|
-
- Registrar el Custom Element con `customElements.define()`
|
|
414
|
-
- Gestionar el ciclo de vida mount/unmount
|
|
415
|
-
- Soportar modo standalone si Wu Framework no esta disponible
|
|
416
|
-
|
|
417
|
-
### Servicio para Componentes
|
|
418
|
-
|
|
419
|
-
```ts
|
|
420
|
-
import { Component, OnInit, OnDestroy } from '@angular/core';
|
|
421
|
-
import { createWuService } from 'wu-framework/adapters/angular';
|
|
422
|
-
|
|
423
|
-
@Component({
|
|
424
|
-
selector: 'app-root',
|
|
425
|
-
template: `<button (click)="sendEvent()">Send Event</button>`
|
|
426
|
-
})
|
|
427
|
-
export class AppComponent implements OnInit, OnDestroy {
|
|
428
|
-
private wuService = createWuService();
|
|
429
|
-
|
|
430
|
-
ngOnInit() {
|
|
431
|
-
this.wuService.on('user:login', (data) => {
|
|
432
|
-
console.log('User logged in:', data);
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
sendEvent() {
|
|
437
|
-
this.wuService.emit('app:ready', { timestamp: Date.now() });
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
ngOnDestroy() {
|
|
441
|
-
this.wuService.destroy();
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
---
|
|
447
|
-
|
|
448
|
-
## Svelte Adapter
|
|
449
|
-
|
|
450
|
-
### Registro Basico
|
|
451
|
-
|
|
452
|
-
```js
|
|
137
|
+
// Svelte 5
|
|
453
138
|
import { wuSvelte } from 'wu-framework/adapters/svelte';
|
|
454
|
-
|
|
139
|
+
wuSvelte.registerSvelte5('dashboard', App);
|
|
455
140
|
|
|
456
|
-
|
|
141
|
+
// Same pattern for Solid, Preact, Lit, Vanilla
|
|
457
142
|
```
|
|
458
143
|
|
|
459
|
-
###
|
|
144
|
+
### 2. Mount from the shell
|
|
460
145
|
|
|
461
146
|
```js
|
|
462
|
-
import {
|
|
463
|
-
import App from './App.svelte';
|
|
464
|
-
|
|
465
|
-
wuSvelte.registerSvelte5('my-app', App);
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
### Stores Reactivos
|
|
469
|
-
|
|
470
|
-
```svelte
|
|
471
|
-
<script>
|
|
472
|
-
import { createWuStore, useWuEvents } from 'wu-framework/adapters/svelte';
|
|
473
|
-
import { onDestroy } from 'svelte';
|
|
474
|
-
|
|
475
|
-
const userStore = createWuStore('user');
|
|
476
|
-
const { emit, on, cleanup } = useWuEvents();
|
|
477
|
-
|
|
478
|
-
on('cart:updated', (data) => {
|
|
479
|
-
console.log('Cart updated:', data);
|
|
480
|
-
});
|
|
147
|
+
import { wu } from 'wu-framework';
|
|
481
148
|
|
|
482
|
-
|
|
483
|
-
|
|
149
|
+
await wu.init({
|
|
150
|
+
apps: [
|
|
151
|
+
{ name: 'header', url: 'http://localhost:3001' },
|
|
152
|
+
{ name: 'sidebar', url: 'http://localhost:3002' },
|
|
153
|
+
{ name: 'content', url: 'http://localhost:3003' },
|
|
154
|
+
]
|
|
155
|
+
});
|
|
484
156
|
|
|
485
|
-
|
|
486
|
-
|
|
157
|
+
await wu.mount('header', '#header-container');
|
|
158
|
+
await wu.mount('sidebar', '#sidebar-container');
|
|
159
|
+
await wu.mount('content', '#content-container');
|
|
487
160
|
```
|
|
488
161
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
## Preact Adapter
|
|
492
|
-
|
|
493
|
-
### Registro Basico
|
|
162
|
+
### 3. Cross-app communication
|
|
494
163
|
|
|
495
|
-
```
|
|
496
|
-
import {
|
|
497
|
-
import App from './App';
|
|
498
|
-
|
|
499
|
-
wuPreact.register('my-app', App);
|
|
500
|
-
```
|
|
501
|
-
|
|
502
|
-
### Compatible con React (preact/compat)
|
|
164
|
+
```js
|
|
165
|
+
import { emit, on, getState, setState } from 'wu-framework';
|
|
503
166
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
167
|
+
// Events
|
|
168
|
+
emit('user:login', { userId: 123 });
|
|
169
|
+
on('user:*', (event) => console.log(event.data));
|
|
507
170
|
|
|
508
|
-
|
|
171
|
+
// Shared store
|
|
172
|
+
setState('user.name', 'John');
|
|
173
|
+
getState('user.name'); // 'John'
|
|
509
174
|
```
|
|
510
175
|
|
|
511
|
-
###
|
|
512
|
-
|
|
513
|
-
```jsx
|
|
514
|
-
import { h } from 'preact';
|
|
515
|
-
import { useState, useEffect, useCallback, useRef } from 'preact/hooks';
|
|
516
|
-
import { createUseWuEvents, createUseWuStore } from 'wu-framework/adapters/preact';
|
|
517
|
-
|
|
518
|
-
const useWuEvents = createUseWuEvents({ useCallback, useEffect, useRef });
|
|
519
|
-
const useWuStore = createUseWuStore({ useState, useCallback, useEffect });
|
|
176
|
+
### 4. Add AI (optional)
|
|
520
177
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
178
|
+
```js
|
|
179
|
+
wu.ai.provider('ollama', {
|
|
180
|
+
endpoint: 'http://localhost:11434/api/chat',
|
|
181
|
+
model: 'llama3',
|
|
182
|
+
});
|
|
524
183
|
|
|
525
|
-
|
|
526
|
-
}
|
|
184
|
+
const response = await wu.ai.send('What apps are mounted?');
|
|
527
185
|
```
|
|
528
186
|
|
|
529
187
|
---
|
|
530
188
|
|
|
531
|
-
##
|
|
532
|
-
|
|
533
|
-
### Registro Basico
|
|
189
|
+
## WuCommerce — Real-World Example
|
|
534
190
|
|
|
535
|
-
|
|
536
|
-
import { wuSolid } from 'wu-framework/adapters/solid';
|
|
537
|
-
import App from './App';
|
|
538
|
-
|
|
539
|
-
wuSolid.register('my-app', App);
|
|
540
|
-
```
|
|
191
|
+
Wu ships with **WuCommerce**, a Shopify-like merchant dashboard where every section is a real micro-app built with a different framework.
|
|
541
192
|
|
|
542
|
-
|
|
193
|
+
| Micro-app | Framework | What it does |
|
|
194
|
+
|-----------|-----------|-------------|
|
|
195
|
+
| **Topbar** | Preact | Store name, nav tabs, search, notifications, theme toggle |
|
|
196
|
+
| **Dashboard** | Svelte 5 | KPI cards, sparklines, recent orders, revenue chart |
|
|
197
|
+
| **Orders** | React | Order table with filters, search, status badges |
|
|
198
|
+
| **Products** | Vue 3 | Product catalog grid, stock badges, category filter |
|
|
199
|
+
| **Customers** | Solid.js | Customer list, segment badges, click-to-filter-orders |
|
|
200
|
+
| **Analytics** | Lit | Revenue bar chart, traffic donut, top products |
|
|
201
|
+
| **Chat** | Vanilla JS | Floating chat widget with conversations and messages |
|
|
202
|
+
| **Settings** | Angular 21 | Store config form, shipping zones, payment methods |
|
|
543
203
|
|
|
544
|
-
|
|
545
|
-
import { createWuStore, createWuEvent } from 'wu-framework/adapters/solid';
|
|
546
|
-
|
|
547
|
-
function MyComponent() {
|
|
548
|
-
const [user, setUser] = createWuStore('user');
|
|
549
|
-
const lastEvent = createWuEvent('notification:*');
|
|
550
|
-
|
|
551
|
-
return (
|
|
552
|
-
<div>
|
|
553
|
-
<p>Hello, {user()?.name}</p>
|
|
554
|
-
<Show when={lastEvent()}>
|
|
555
|
-
<p>Last notification: {lastEvent()?.data}</p>
|
|
556
|
-
</Show>
|
|
557
|
-
<button onClick={() => setUser('name', 'John')}>
|
|
558
|
-
Set Name
|
|
559
|
-
</button>
|
|
560
|
-
</div>
|
|
561
|
-
);
|
|
562
|
-
}
|
|
563
|
-
```
|
|
204
|
+
All 8 apps communicate through Wu's event bus and shared store. Click a customer → orders filter. Toggle theme → all 8 apps update. Change store name in settings → topbar updates.
|
|
564
205
|
|
|
565
206
|
---
|
|
566
207
|
|
|
567
|
-
##
|
|
568
|
-
|
|
569
|
-
### Registro con LitElement
|
|
570
|
-
|
|
571
|
-
```js
|
|
572
|
-
import { LitElement, html, css } from 'lit';
|
|
573
|
-
import { wuLit } from 'wu-framework/adapters/lit';
|
|
574
|
-
|
|
575
|
-
class MyApp extends LitElement {
|
|
576
|
-
static styles = css`
|
|
577
|
-
:host { display: block; padding: 16px; }
|
|
578
|
-
`;
|
|
579
|
-
|
|
580
|
-
render() {
|
|
581
|
-
return html`<h1>Hello from Lit!</h1>`;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
wuLit.register('my-app', MyApp);
|
|
586
|
-
```
|
|
208
|
+
## 3 Sandbox Strategies
|
|
587
209
|
|
|
588
|
-
|
|
210
|
+
| Mode | How it works | Tree shaking | Source maps | HMR | JS isolation |
|
|
211
|
+
|------|-------------|:---:|:---:|:---:|:---:|
|
|
212
|
+
| `module` (default) | `import()` + Proxy side-effect tracking | Yes | Yes | Yes | Side effects only |
|
|
213
|
+
| `strict` | Hidden iframe + real `import()` | Yes | Yes | Yes | **Full** (separate window) |
|
|
214
|
+
| `eval` | Fetch HTML → parse → `with(proxy){}` | No | No | No | **Full** (proxy traps) |
|
|
589
215
|
|
|
590
216
|
```js
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
console.log('User logged in:', data);
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
handleClick() {
|
|
603
|
-
this.wuEmit('button:clicked', { id: 'my-button' });
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
render() {
|
|
607
|
-
return html`
|
|
608
|
-
<button @click=${this.handleClick}>Click me</button>
|
|
609
|
-
`;
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
wuLit.register('my-app', MyApp);
|
|
217
|
+
await wu.init({
|
|
218
|
+
apps: [
|
|
219
|
+
{ name: 'header', url: '...', sandbox: 'module' },
|
|
220
|
+
{ name: 'analytics', url: '...', sandbox: 'strict' },
|
|
221
|
+
{ name: 'legacy', url: '...', sandbox: 'eval' },
|
|
222
|
+
]
|
|
223
|
+
});
|
|
614
224
|
```
|
|
615
225
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
```js
|
|
619
|
-
import { wuLit } from 'wu-framework/adapters/lit';
|
|
620
|
-
|
|
621
|
-
class MyComponent extends HTMLElement {
|
|
622
|
-
connectedCallback() {
|
|
623
|
-
this.attachShadow({ mode: 'open' });
|
|
624
|
-
this.shadowRoot.innerHTML = '<h1>Hello Web Component!</h1>';
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
wuLit.registerWebComponent('my-component', MyComponent);
|
|
629
|
-
```
|
|
226
|
+
**Auto-cleaned on unmount:** timers, intervals, rAF, event listeners, localStorage keys, DOM mutations.
|
|
630
227
|
|
|
631
228
|
---
|
|
632
229
|
|
|
633
|
-
##
|
|
230
|
+
## 3 CSS Isolation Modes
|
|
634
231
|
|
|
635
|
-
|
|
232
|
+
| Mode | What happens | When to use |
|
|
233
|
+
|------|-------------|-------------|
|
|
234
|
+
| `shared` | Host styles injected into Shadow DOM | Apps sharing a design system (Tailwind) |
|
|
235
|
+
| `isolated` | Pure Shadow DOM — no external styles | Fully independent apps |
|
|
236
|
+
| `fully-isolated` | Only the app's own styles | Apps that need their CSS but not global CSS |
|
|
636
237
|
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
wuVanilla.register('my-app', {
|
|
641
|
-
state: { count: 0 },
|
|
642
|
-
|
|
643
|
-
render: (container, state) => {
|
|
644
|
-
container.innerHTML = `
|
|
645
|
-
<div>
|
|
646
|
-
<h1>Count: ${state.count}</h1>
|
|
647
|
-
<button id="increment">+</button>
|
|
648
|
-
</div>
|
|
649
|
-
`;
|
|
650
|
-
container.querySelector('#increment').onclick = () => {
|
|
651
|
-
state.count++;
|
|
652
|
-
};
|
|
653
|
-
},
|
|
654
|
-
|
|
655
|
-
destroy: (container) => {
|
|
656
|
-
container.innerHTML = '';
|
|
657
|
-
}
|
|
658
|
-
});
|
|
238
|
+
```json
|
|
239
|
+
{ "name": "my-app", "entry": "index.js", "styleMode": "isolated" }
|
|
659
240
|
```
|
|
660
241
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
```js
|
|
664
|
-
import { wuVanilla } from 'wu-framework/adapters/vanilla';
|
|
665
|
-
|
|
666
|
-
class TodoApp {
|
|
667
|
-
constructor(container) {
|
|
668
|
-
this.container = container;
|
|
669
|
-
this.todos = [];
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
render() {
|
|
673
|
-
this.container.innerHTML = `
|
|
674
|
-
<ul>
|
|
675
|
-
${this.todos.map(t => `<li>${t}</li>`).join('')}
|
|
676
|
-
</ul>
|
|
677
|
-
<input type="text" id="input" />
|
|
678
|
-
<button id="add">Add</button>
|
|
679
|
-
`;
|
|
680
|
-
|
|
681
|
-
this.container.querySelector('#add').onclick = () => {
|
|
682
|
-
const input = this.container.querySelector('#input');
|
|
683
|
-
this.todos.push(input.value);
|
|
684
|
-
this.render();
|
|
685
|
-
};
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
destroy() {
|
|
689
|
-
this.container.innerHTML = '';
|
|
690
|
-
}
|
|
691
|
-
}
|
|
242
|
+
---
|
|
692
243
|
|
|
693
|
-
|
|
694
|
-
```
|
|
244
|
+
## AI Paradigms
|
|
695
245
|
|
|
696
|
-
###
|
|
246
|
+
### 1. App → LLM → App
|
|
697
247
|
|
|
698
248
|
```js
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
wuVanilla.registerTemplate('header', `
|
|
702
|
-
<header>
|
|
703
|
-
<h1>My Header</h1>
|
|
704
|
-
<nav>
|
|
705
|
-
<a href="/">Home</a>
|
|
706
|
-
<a href="/about">About</a>
|
|
707
|
-
</nav>
|
|
708
|
-
</header>
|
|
709
|
-
`);
|
|
710
|
-
|
|
711
|
-
// Template dinamico
|
|
712
|
-
wuVanilla.registerTemplate('greeting',
|
|
713
|
-
(data) => `<h1>Hello, ${data.name}!</h1>`,
|
|
714
|
-
{ data: { name: 'World' } }
|
|
715
|
-
);
|
|
249
|
+
const response = await wu.ai.send('What items are in the cart?');
|
|
716
250
|
```
|
|
717
251
|
|
|
718
|
-
###
|
|
252
|
+
### 2. LLM → App → LLM (WebMCP)
|
|
719
253
|
|
|
720
254
|
```js
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
const Counter = wuVanilla.createComponent({
|
|
724
|
-
state: { count: 0 },
|
|
725
|
-
|
|
726
|
-
template: (state) => `
|
|
727
|
-
<div>
|
|
728
|
-
<h1>Count: ${state.count}</h1>
|
|
729
|
-
<button data-action="increment">+</button>
|
|
730
|
-
<button data-action="decrement">-</button>
|
|
731
|
-
</div>
|
|
732
|
-
`,
|
|
733
|
-
|
|
734
|
-
actions: {
|
|
735
|
-
increment: (state) => ({ count: state.count + 1 }),
|
|
736
|
-
decrement: (state) => ({ count: state.count - 1 })
|
|
737
|
-
}
|
|
738
|
-
});
|
|
739
|
-
|
|
740
|
-
wuVanilla.register('counter', Counter);
|
|
255
|
+
wu.ai.expose(); // Registers all tools via navigator.modelContext (Chrome 146+)
|
|
741
256
|
```
|
|
742
257
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
## Event Bus
|
|
746
|
-
|
|
747
|
-
Sistema de eventos para comunicacion entre microfrontends con soporte para wildcards y replay.
|
|
258
|
+
### 3. Autonomous Agent
|
|
748
259
|
|
|
749
260
|
```js
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
emit('user:login', { userId: 123, name: 'John' });
|
|
754
|
-
|
|
755
|
-
// Suscribirse a evento
|
|
756
|
-
const unsubscribe = on('user:login', (event) => {
|
|
757
|
-
console.log('User logged in:', event.data);
|
|
758
|
-
});
|
|
759
|
-
|
|
760
|
-
// Suscribirse con wildcards
|
|
761
|
-
on('user:*', (event) => {
|
|
762
|
-
console.log('User event:', event.name, event.data);
|
|
763
|
-
});
|
|
764
|
-
|
|
765
|
-
// Suscribirse una sola vez
|
|
766
|
-
once('app:ready', (event) => {
|
|
767
|
-
console.log('App is ready!');
|
|
768
|
-
});
|
|
769
|
-
|
|
770
|
-
// Desuscribirse
|
|
771
|
-
off('user:login', callback);
|
|
772
|
-
unsubscribe();
|
|
773
|
-
|
|
774
|
-
// Replay eventos del historial
|
|
775
|
-
replayEvents('user:*', (event) => {
|
|
776
|
-
console.log('Past event:', event);
|
|
777
|
-
});
|
|
261
|
+
for await (const step of wu.ai.agent('Find the top customer and show their profile')) {
|
|
262
|
+
console.log(`Step ${step.step}: ${step.content}`);
|
|
263
|
+
}
|
|
778
264
|
```
|
|
779
265
|
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
## Store (State Management)
|
|
783
|
-
|
|
784
|
-
Store de alto rendimiento con pattern matching.
|
|
266
|
+
### 4. Cross-App Orchestration
|
|
785
267
|
|
|
786
268
|
```js
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
setState,
|
|
790
|
-
onStateChange,
|
|
791
|
-
batchState,
|
|
792
|
-
clearState,
|
|
793
|
-
getStoreMetrics
|
|
794
|
-
} from 'wu-framework';
|
|
795
|
-
|
|
796
|
-
// Establecer estado (dot notation)
|
|
797
|
-
setState('user.name', 'John');
|
|
798
|
-
setState('user.preferences.theme', 'dark');
|
|
799
|
-
|
|
800
|
-
// Obtener estado
|
|
801
|
-
const name = getState('user.name'); // 'John'
|
|
802
|
-
const user = getState('user'); // { name: 'John', preferences: { theme: 'dark' } }
|
|
803
|
-
|
|
804
|
-
// Suscribirse a cambios
|
|
805
|
-
const unsubscribe = onStateChange('user.name', (value, path) => {
|
|
806
|
-
console.log(`${path} changed to:`, value);
|
|
807
|
-
});
|
|
808
|
-
|
|
809
|
-
// Suscribirse con wildcards
|
|
810
|
-
onStateChange('user.*', (value, path) => {
|
|
811
|
-
console.log(`User property changed: ${path} =`, value);
|
|
812
|
-
});
|
|
813
|
-
|
|
814
|
-
// Batch updates (mas eficiente)
|
|
815
|
-
batchState({
|
|
816
|
-
'user.name': 'Jane',
|
|
817
|
-
'user.email': 'jane@example.com',
|
|
818
|
-
'settings.notifications': true
|
|
819
|
-
});
|
|
820
|
-
|
|
821
|
-
// Metricas de performance
|
|
822
|
-
const metrics = getStoreMetrics();
|
|
269
|
+
const result = await wu.ai.intent('Find customer Emma and refund order #4821');
|
|
270
|
+
console.log(result.appsInvolved); // ['customers', 'orders']
|
|
823
271
|
```
|
|
824
272
|
|
|
825
273
|
---
|
|
826
274
|
|
|
827
|
-
##
|
|
275
|
+
## Plugins & Hooks
|
|
828
276
|
|
|
829
277
|
```js
|
|
830
|
-
import { usePlugin, createPlugin,
|
|
278
|
+
import { usePlugin, createPlugin, useHook } from 'wu-framework';
|
|
831
279
|
|
|
832
|
-
|
|
280
|
+
usePlugin(createPlugin({
|
|
833
281
|
name: 'analytics',
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
api.on('app:mounted', (event) => {
|
|
838
|
-
trackEvent('mount', event.data.appName);
|
|
839
|
-
});
|
|
840
|
-
},
|
|
841
|
-
|
|
842
|
-
beforeMount: async (context) => {
|
|
843
|
-
console.log('Before mount:', context.appName);
|
|
844
|
-
},
|
|
845
|
-
|
|
846
|
-
afterMount: async (context) => {
|
|
847
|
-
console.log('Mounted in', context.mountTime, 'ms');
|
|
848
|
-
}
|
|
849
|
-
});
|
|
850
|
-
|
|
851
|
-
usePlugin(analyticsPlugin, { trackingId: 'UA-123456' });
|
|
852
|
-
```
|
|
853
|
-
|
|
854
|
-
---
|
|
855
|
-
|
|
856
|
-
## Lifecycle Hooks
|
|
282
|
+
install: (api) => api.on('app:mounted', (e) => track(e)),
|
|
283
|
+
afterMount: async (ctx) => log('mounted in', ctx.mountTime, 'ms')
|
|
284
|
+
}));
|
|
857
285
|
|
|
858
|
-
```js
|
|
859
|
-
import { useHook, createGuardHook, createTimedHook } from 'wu-framework';
|
|
860
|
-
|
|
861
|
-
// Hook basico
|
|
862
286
|
useHook('beforeMount', async (context, next) => {
|
|
863
|
-
console.log('
|
|
287
|
+
console.log('Mounting:', context.appName);
|
|
864
288
|
await next();
|
|
865
|
-
}, { name: 'my-hook', priority: 10 });
|
|
866
|
-
|
|
867
|
-
// Guard hook (puede cancelar)
|
|
868
|
-
const authGuard = createGuardHook(async (ctx) => {
|
|
869
|
-
return await isUserAuthenticated();
|
|
870
289
|
});
|
|
871
|
-
useHook('beforeMount', authGuard);
|
|
872
|
-
|
|
873
|
-
// Hook con timeout
|
|
874
|
-
const timedHook = createTimedHook(async (ctx) => {
|
|
875
|
-
await slowOperation();
|
|
876
|
-
}, 5000);
|
|
877
290
|
```
|
|
878
291
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
| Fase | Descripcion |
|
|
882
|
-
|------|-------------|
|
|
883
|
-
| `beforeInit` | Antes de inicializar framework |
|
|
884
|
-
| `afterInit` | Despues de inicializar |
|
|
885
|
-
| `beforeLoad` | Antes de cargar una app |
|
|
886
|
-
| `afterLoad` | Despues de cargar |
|
|
887
|
-
| `beforeMount` | Antes de montar |
|
|
888
|
-
| `afterMount` | Despues de montar |
|
|
889
|
-
| `beforeUnmount` | Antes de desmontar |
|
|
890
|
-
| `afterUnmount` | Despues de desmontar |
|
|
292
|
+
Phases: `beforeInit` → `afterInit` → `beforeLoad` → `afterLoad` → `beforeMount` → `afterMount` → `beforeUnmount` → `afterUnmount`
|
|
891
293
|
|
|
892
294
|
---
|
|
893
295
|
|
|
894
|
-
##
|
|
296
|
+
## Prefetch (Speculation Rules API)
|
|
895
297
|
|
|
896
298
|
```js
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
{ name: 'sidebar', url: '/mfe/sidebar', strategy: 'eager' },
|
|
901
|
-
{ name: 'footer', url: '/mfe/footer', strategy: 'preload' },
|
|
902
|
-
{ name: 'analytics', url: '/mfe/analytics', strategy: 'idle' }
|
|
903
|
-
]
|
|
904
|
-
});
|
|
299
|
+
wu.prefetch(['sidebar', 'analytics']);
|
|
300
|
+
wu.prefetch(['sidebar'], { trigger: 'hover', action: 'prerender' });
|
|
301
|
+
wu.prefetchAll();
|
|
905
302
|
```
|
|
906
303
|
|
|
907
|
-
|
|
908
|
-
|------------|-------------|-----------------|
|
|
909
|
-
| `lazy` | Carga cuando se monta (default) | Contenido below-the-fold |
|
|
910
|
-
| `eager` | Precarga inmediata | Componentes criticos |
|
|
911
|
-
| `preload` | Usa `<link rel="prefetch">` | Navegacion anticipada |
|
|
912
|
-
| `idle` | Usa `requestIdleCallback` | Analytics, features secundarias |
|
|
304
|
+
Fallback chain: Speculation Rules API (Chrome 121+) → `<link rel="modulepreload">` → `<link rel="prefetch">`
|
|
913
305
|
|
|
914
306
|
---
|
|
915
307
|
|
|
916
|
-
##
|
|
308
|
+
## Cookie Overrides for QA
|
|
917
309
|
|
|
918
310
|
```js
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
getPerformanceMetrics,
|
|
923
|
-
generatePerformanceReport
|
|
924
|
-
} from 'wu-framework';
|
|
925
|
-
|
|
926
|
-
// Medicion personalizada
|
|
927
|
-
startMeasure('data-fetch', 'my-app');
|
|
928
|
-
await fetchData();
|
|
929
|
-
const duration = endMeasure('data-fetch', 'my-app');
|
|
930
|
-
|
|
931
|
-
// Reporte completo
|
|
932
|
-
const report = generatePerformanceReport();
|
|
311
|
+
wu.override('sidebar', 'http://localhost:5174');
|
|
312
|
+
wu.getOverrides(); // { sidebar: 'http://localhost:5174' }
|
|
313
|
+
wu.removeOverride('sidebar');
|
|
933
314
|
```
|
|
934
315
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
## Error Handling
|
|
938
|
-
|
|
939
|
-
```js
|
|
940
|
-
import { registerErrorHandler, configureErrorBoundary } from 'wu-framework';
|
|
941
|
-
|
|
942
|
-
registerErrorHandler({
|
|
943
|
-
name: 'api-error',
|
|
944
|
-
canHandle: (error) => error.message.includes('API'),
|
|
945
|
-
handle: async (error, context) => {
|
|
946
|
-
if (context.retryCount < 3) {
|
|
947
|
-
return { recovered: true, action: 'retry' };
|
|
948
|
-
}
|
|
949
|
-
return { recovered: false, action: 'fallback' };
|
|
950
|
-
}
|
|
951
|
-
});
|
|
952
|
-
|
|
953
|
-
configureErrorBoundary({
|
|
954
|
-
maxRetries: 3,
|
|
955
|
-
retryDelay: 1000,
|
|
956
|
-
showErrorUI: true
|
|
957
|
-
});
|
|
958
|
-
```
|
|
316
|
+
QA sets a cookie → only **their browser** sees the override. Everyone else sees production. 3-layer security: environment gate, domain allowlist, visual indicator.
|
|
959
317
|
|
|
960
318
|
---
|
|
961
319
|
|
|
962
|
-
##
|
|
963
|
-
|
|
964
|
-
```js
|
|
965
|
-
import { wu } from 'wu-framework';
|
|
966
|
-
|
|
967
|
-
const header = wu.app('header', {
|
|
968
|
-
url: 'http://localhost:3001',
|
|
969
|
-
container: '#header-container'
|
|
970
|
-
});
|
|
971
|
-
|
|
972
|
-
await header.mount();
|
|
973
|
-
console.log(header.isMounted); // true
|
|
974
|
-
|
|
975
|
-
await header.unmount();
|
|
976
|
-
await header.remount();
|
|
977
|
-
await header.reload(); // Limpia cache
|
|
320
|
+
## Project Stats
|
|
978
321
|
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
322
|
+
| Metric | Value |
|
|
323
|
+
|---|---|
|
|
324
|
+
| Source files | 79 |
|
|
325
|
+
| Lines of code | 23,442 |
|
|
326
|
+
| Test cases | **650** |
|
|
327
|
+
| Framework adapters | 8 |
|
|
328
|
+
| AI modules | 12 |
|
|
329
|
+
| Core modules | 23 |
|
|
330
|
+
| Runtime dependencies | **0** |
|
|
331
|
+
| Bundle (ESM, minified) | ~174 KB |
|
|
982
332
|
|
|
983
333
|
---
|
|
984
334
|
|
|
985
|
-
##
|
|
986
|
-
|
|
987
|
-
Wu Framework incluye un sistema de build completo para proteger el codigo.
|
|
988
|
-
|
|
989
|
-
### Comandos Disponibles
|
|
335
|
+
## Build
|
|
990
336
|
|
|
991
337
|
```bash
|
|
992
|
-
#
|
|
993
|
-
npm
|
|
994
|
-
|
|
995
|
-
# Build completo (todos los formatos)
|
|
996
|
-
npm run build
|
|
997
|
-
|
|
998
|
-
# Builds individuales
|
|
999
|
-
npm run build:dev # Desarrollo (sin minificar)
|
|
1000
|
-
npm run build:prod # Produccion (minificado)
|
|
1001
|
-
npm run build:obf # Ofuscado
|
|
1002
|
-
npm run build:umd # UMD para browsers
|
|
1003
|
-
npm run build:cjs # CommonJS para Node
|
|
1004
|
-
|
|
1005
|
-
# Build protegido (pipeline completo)
|
|
1006
|
-
npm run build:protected # Bundle -> Minify -> Obfuscate -> Base64
|
|
338
|
+
npm run build # ESM + CJS + UMD + Dev
|
|
339
|
+
npm run test # 650 tests (Vitest)
|
|
340
|
+
npm run test:coverage # Coverage report
|
|
1007
341
|
```
|
|
1008
342
|
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
[1] Bundle (Rollup) -> Empaqueta todos los modulos
|
|
1016
|
-
|
|
|
1017
|
-
v
|
|
1018
|
-
[2] Minify (Terser) -> Reduce ~60% del tamanio
|
|
1019
|
-
|
|
|
1020
|
-
v
|
|
1021
|
-
[3] Obfuscate -> Codigo ilegible
|
|
1022
|
-
|
|
|
1023
|
-
v
|
|
1024
|
-
[4] Base64 Encode -> Capa adicional de proteccion
|
|
1025
|
-
|
|
|
1026
|
-
v
|
|
1027
|
-
Output: wu-framework.protected.js (~250KB)
|
|
1028
|
-
```
|
|
1029
|
-
|
|
1030
|
-
### Archivos Generados
|
|
1031
|
-
|
|
1032
|
-
| Archivo | Formato | Uso |
|
|
1033
|
-
|---------|---------|-----|
|
|
1034
|
-
| `wu-framework.dev.js` | ES Module | Desarrollo |
|
|
1035
|
-
| `wu-framework.min.js` | ES Module | Produccion |
|
|
1036
|
-
| `wu-framework.obf.js` | ES Module | Produccion protegida |
|
|
1037
|
-
| `wu-framework.protected.js` | ES Module | Maxima proteccion |
|
|
1038
|
-
| `wu-framework.umd.js` | UMD | Browsers via CDN |
|
|
1039
|
-
| `wu-framework.cjs.js` | CommonJS | Node.js |
|
|
343
|
+
| Output | Format | Use |
|
|
344
|
+
|--------|--------|-----|
|
|
345
|
+
| `wu-framework.esm.js` | ES Module | Bundler imports |
|
|
346
|
+
| `wu-framework.cjs.js` | CommonJS | Node.js require |
|
|
347
|
+
| `wu-framework.umd.js` | UMD | CDN / script tag |
|
|
348
|
+
| `wu-framework.dev.js` | ES Module | Development |
|
|
1040
349
|
|
|
1041
350
|
---
|
|
1042
351
|
|
|
1043
|
-
##
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
352
|
+
## Architecture
|
|
353
|
+
|
|
354
|
+
```
|
|
355
|
+
┌───────────────────────────────────────────────────────────────────────┐
|
|
356
|
+
│ SHELL (any framework) │
|
|
357
|
+
├──────────┬──────────┬──────────┬──────────┬──────────┬───────────────┤
|
|
358
|
+
│ Shadow │ Shadow │ Shadow │ Shadow │ Shadow │ Shadow ... │
|
|
359
|
+
│ ┌──────┐ │ ┌──────┐ │ ┌──────┐ │ ┌──────┐ │ ┌──────┐ │ ┌──────┐ │
|
|
360
|
+
│ │Topbar│ │ │Dashbd│ │ │Orders│ │ │Produc│ │ │Custo.│ │ │Analyt│ │
|
|
361
|
+
│ │Preact│ │ │Svelte│ │ │React │ │ │Vue 3 │ │ │Solid │ │ │ Lit │ │
|
|
362
|
+
│ └──────┘ │ └──────┘ │ └──────┘ │ └──────┘ │ └──────┘ │ └──────┘ │
|
|
363
|
+
├──────────┴──────────┴──────────┴──────────┴──────────┴───────────────┤
|
|
364
|
+
│ WU FRAMEWORK CORE │
|
|
365
|
+
│ Sandbox (module/strict/eval) · EventBus (wildcards, replay) │
|
|
366
|
+
│ Store (dot-paths, batch) · StyleBridge (shared/isolated/fully-iso) │
|
|
367
|
+
│ Loader · Hooks · Plugins · Cache · Prefetch · Overrides │
|
|
368
|
+
├──────────────────────────────────────────────────────────────────────┤
|
|
369
|
+
│ WU AI (BYOL) │
|
|
370
|
+
│ Provider · Actions · Agent · Orchestrate · Triggers · Context │
|
|
371
|
+
│ Browser Actions · WebMCP · MCP Server · Workflows · Security │
|
|
372
|
+
└──────────────────────────────────────────────────────────────────────┘
|
|
1063
373
|
```
|
|
1064
374
|
|
|
1065
375
|
---
|
|
1066
376
|
|
|
1067
|
-
##
|
|
377
|
+
## Documentation
|
|
1068
378
|
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
```
|
|
1072
|
-
https://cdn.mycompany.com/
|
|
1073
|
-
├── mfe/
|
|
1074
|
-
│ ├── header/
|
|
1075
|
-
│ │ ├── wu.json
|
|
1076
|
-
│ │ ├── index.js
|
|
1077
|
-
│ │ └── assets/
|
|
1078
|
-
│ ├── sidebar/
|
|
1079
|
-
│ │ ├── wu.json
|
|
1080
|
-
│ │ ├── index.js
|
|
1081
|
-
│ │ └── assets/
|
|
1082
|
-
│ └── content/
|
|
1083
|
-
│ ├── wu.json
|
|
1084
|
-
│ ├── index.js
|
|
1085
|
-
│ └── assets/
|
|
1086
|
-
```
|
|
379
|
+
Full documentation at **[wu-framework.dev](https://wu-framework.dev)**
|
|
1087
380
|
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
content: 'https://staging-cdn.mycompany.com/mfe/content'
|
|
1101
|
-
},
|
|
1102
|
-
production: {
|
|
1103
|
-
header: 'https://cdn.mycompany.com/mfe/header',
|
|
1104
|
-
sidebar: 'https://cdn.mycompany.com/mfe/sidebar',
|
|
1105
|
-
content: 'https://cdn.mycompany.com/mfe/content'
|
|
1106
|
-
}
|
|
1107
|
-
};
|
|
1108
|
-
|
|
1109
|
-
const env = process.env.NODE_ENV || 'development';
|
|
1110
|
-
const urls = config[env];
|
|
1111
|
-
|
|
1112
|
-
await wu.init({
|
|
1113
|
-
apps: [
|
|
1114
|
-
{ name: 'header', url: urls.header },
|
|
1115
|
-
{ name: 'sidebar', url: urls.sidebar },
|
|
1116
|
-
{ name: 'content', url: urls.content }
|
|
1117
|
-
]
|
|
1118
|
-
});
|
|
1119
|
-
```
|
|
1120
|
-
|
|
1121
|
-
### CORS Configuration
|
|
1122
|
-
|
|
1123
|
-
```nginx
|
|
1124
|
-
location /mfe/ {
|
|
1125
|
-
add_header Access-Control-Allow-Origin *;
|
|
1126
|
-
add_header Access-Control-Allow-Methods "GET, OPTIONS";
|
|
1127
|
-
add_header Access-Control-Allow-Headers "Content-Type";
|
|
1128
|
-
}
|
|
1129
|
-
```
|
|
1130
|
-
|
|
1131
|
-
### Versionado
|
|
1132
|
-
|
|
1133
|
-
```json
|
|
1134
|
-
{
|
|
1135
|
-
"name": "header",
|
|
1136
|
-
"version": "1.2.0",
|
|
1137
|
-
"entry": "index.js"
|
|
1138
|
-
}
|
|
1139
|
-
```
|
|
1140
|
-
|
|
1141
|
-
```js
|
|
1142
|
-
await wu.init({
|
|
1143
|
-
apps: [
|
|
1144
|
-
{ name: 'header', url: 'https://cdn.mycompany.com/mfe/header/v1.2.0' },
|
|
1145
|
-
{ name: 'sidebar', url: 'https://cdn.mycompany.com/mfe/sidebar/v2.0.0' }
|
|
1146
|
-
]
|
|
1147
|
-
});
|
|
1148
|
-
```
|
|
381
|
+
- [Quick Start](https://wu-framework.dev/docs/quick-start) — Get running in 5 minutes
|
|
382
|
+
- [Getting Started](https://wu-framework.dev/docs/getting-started) — Deeper tutorial with cross-app communication
|
|
383
|
+
- [API Reference](https://wu-framework.dev/docs/core/api) — Full API docs
|
|
384
|
+
- [Event Bus](https://wu-framework.dev/docs/core/event-bus) — Inter-app communication
|
|
385
|
+
- [Shared Store](https://wu-framework.dev/docs/core/store) — Cross-app reactive state
|
|
386
|
+
- [Sandbox](https://wu-framework.dev/docs/core/sandbox) — JS isolation strategies
|
|
387
|
+
- [AI Overview](https://wu-framework.dev/docs/ai/overview) — 4 AI paradigms
|
|
388
|
+
- [AI Actions](https://wu-framework.dev/docs/ai/actions) — Register tools for the LLM
|
|
389
|
+
- [Browser Actions](https://wu-framework.dev/docs/ai/browser-actions) — 10 built-in browser tools
|
|
390
|
+
- [MCP Server](https://wu-framework.dev/docs/ai/mcp-server) — Connect AI agents to live apps
|
|
391
|
+
- [CSS Isolation](https://wu-framework.dev/docs/guides/css-isolation) — Shadow DOM style modes
|
|
392
|
+
- [Deployment](https://wu-framework.dev/docs/guides/deployment) — Production deployment guide
|
|
1149
393
|
|
|
1150
394
|
---
|
|
1151
395
|
|
|
1152
|
-
##
|
|
1153
|
-
|
|
1154
|
-
```
|
|
1155
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
1156
|
-
│ HOST APPLICATION │
|
|
1157
|
-
├─────────────────────────────────────────────────────────────┤
|
|
1158
|
-
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
|
|
1159
|
-
│ │ #shadow-root │ │ #shadow-root │ │ #shadow-root│ │
|
|
1160
|
-
│ │ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌─────────┐ │ │
|
|
1161
|
-
│ │ │ Header │ │ │ │ Sidebar │ │ │ │ Content │ │ │
|
|
1162
|
-
│ │ │ (React) │ │ │ │ (Vue) │ │ │ │(Angular)│ │ │
|
|
1163
|
-
│ │ └───────────┘ │ │ └───────────┘ │ │ └─────────┘ │ │
|
|
1164
|
-
│ │ CSS Isolated │ │ CSS Isolated │ │ CSS Isolated│ │
|
|
1165
|
-
│ │ JS Sandboxed │ │ JS Sandboxed │ │ JS Sandboxed│ │
|
|
1166
|
-
│ └─────────────────┘ └─────────────────┘ └─────────────┘ │
|
|
1167
|
-
├─────────────────────────────────────────────────────────────┤
|
|
1168
|
-
│ WU FRAMEWORK CORE │
|
|
1169
|
-
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │
|
|
1170
|
-
│ │ EventBus │ │ Store │ │ Plugins │ │ Sandbox Pool │ │
|
|
1171
|
-
│ └──────────┘ └──────────┘ └──────────┘ └────────────────┘ │
|
|
1172
|
-
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │
|
|
1173
|
-
│ │ Loader │ │ Manifest │ │ Hooks │ │ Style Bridge │ │
|
|
1174
|
-
│ └──────────┘ └──────────┘ └──────────┘ └────────────────┘ │
|
|
1175
|
-
└─────────────────────────────────────────────────────────────┘
|
|
1176
|
-
```
|
|
396
|
+
## Browser Support
|
|
1177
397
|
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
## API Reference
|
|
1181
|
-
|
|
1182
|
-
### Core
|
|
1183
|
-
|
|
1184
|
-
```js
|
|
1185
|
-
import { wu, init, mount, unmount, destroy, getStats } from 'wu-framework';
|
|
1186
|
-
```
|
|
1187
|
-
|
|
1188
|
-
### Event Bus
|
|
1189
|
-
|
|
1190
|
-
```js
|
|
1191
|
-
import { emit, on, once, off, replayEvents, getEventBusStats } from 'wu-framework';
|
|
1192
|
-
```
|
|
1193
|
-
|
|
1194
|
-
### Store
|
|
1195
|
-
|
|
1196
|
-
```js
|
|
1197
|
-
import { getState, setState, onStateChange, batchState, clearState } from 'wu-framework';
|
|
1198
|
-
```
|
|
1199
|
-
|
|
1200
|
-
### Plugins & Hooks
|
|
1201
|
-
|
|
1202
|
-
```js
|
|
1203
|
-
import { usePlugin, createPlugin, useHook, removeHook } from 'wu-framework';
|
|
1204
|
-
```
|
|
1205
|
-
|
|
1206
|
-
### Performance & Errors
|
|
1207
|
-
|
|
1208
|
-
```js
|
|
1209
|
-
import { startMeasure, endMeasure, generatePerformanceReport } from 'wu-framework';
|
|
1210
|
-
import { registerErrorHandler, configureErrorBoundary } from 'wu-framework';
|
|
1211
|
-
```
|
|
1212
|
-
|
|
1213
|
-
### Style Management
|
|
1214
|
-
|
|
1215
|
-
```js
|
|
1216
|
-
import { configureStyleSharing, reinjectStyles, getStyleStats } from 'wu-framework';
|
|
1217
|
-
```
|
|
1218
|
-
|
|
1219
|
-
### Adapters
|
|
1220
|
-
|
|
1221
|
-
```js
|
|
1222
|
-
import { wuReact } from 'wu-framework/adapters/react';
|
|
1223
|
-
import { wuVue } from 'wu-framework/adapters/vue';
|
|
1224
|
-
import { wuAngular } from 'wu-framework/adapters/angular';
|
|
1225
|
-
import { wuSvelte } from 'wu-framework/adapters/svelte';
|
|
1226
|
-
import { wuPreact } from 'wu-framework/adapters/preact';
|
|
1227
|
-
import { wuSolid } from 'wu-framework/adapters/solid';
|
|
1228
|
-
import { wuLit } from 'wu-framework/adapters/lit';
|
|
1229
|
-
import { wuVanilla } from 'wu-framework/adapters/vanilla';
|
|
1230
|
-
```
|
|
1231
|
-
|
|
1232
|
-
### Utilities
|
|
1233
|
-
|
|
1234
|
-
```js
|
|
1235
|
-
import { presets, dev, events } from 'wu-framework';
|
|
1236
|
-
|
|
1237
|
-
// Presets
|
|
1238
|
-
await wu.init(presets.development([{ name: 'app', port: 3001 }]));
|
|
1239
|
-
await wu.init(presets.production([{ name: 'app', url: 'https://...' }]));
|
|
1240
|
-
|
|
1241
|
-
// Dev tools
|
|
1242
|
-
dev.enableDebug();
|
|
1243
|
-
dev.inspect();
|
|
1244
|
-
await dev.reload('app');
|
|
1245
|
-
|
|
1246
|
-
// Silenciar logs
|
|
1247
|
-
wu.silence();
|
|
1248
|
-
wu.verbose();
|
|
1249
|
-
```
|
|
1250
|
-
|
|
1251
|
-
---
|
|
398
|
+
Chrome 80+, Firefox 78+, Safari 14+, Edge 80+. Shadow DOM v1 required.
|
|
1252
399
|
|
|
1253
400
|
## Contributing
|
|
1254
401
|
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
1. **Fork** el repositorio
|
|
1258
|
-
2. **Crear** branch (`git checkout -b feature/amazing-feature`)
|
|
1259
|
-
3. **Commit** tus cambios (`git commit -m 'Add amazing feature'`)
|
|
1260
|
-
4. **Push** al branch (`git push origin feature/amazing-feature`)
|
|
1261
|
-
5. **Abrir** un Pull Request
|
|
1262
|
-
|
|
1263
|
-
---
|
|
402
|
+
Contributions welcome. Please open an issue first to discuss what you'd like to change.
|
|
1264
403
|
|
|
1265
404
|
## License
|
|
1266
405
|
|
|
1267
|
-
MIT
|
|
1268
|
-
|
|
1269
|
-
---
|
|
1270
|
-
|
|
1271
|
-
**Wu Framework - Universal Microfrontends Made Simple**
|
|
406
|
+
[MIT](./LICENSE) — Free for personal and commercial use.
|
|
1272
407
|
|
|
1273
|
-
|
|
408
|
+
See [LICENSE-COMMERCIAL.md](./LICENSE-COMMERCIAL.md) for optional enterprise support and consulting.
|