wu-framework 1.1.8 → 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -1
- package/README.md +227 -626
- package/dist/wu-framework.cjs.js +1 -1
- package/dist/wu-framework.cjs.js.map +1 -1
- package/dist/wu-framework.dev.js +2988 -1076
- package/dist/wu-framework.dev.js.map +1 -1
- package/dist/wu-framework.esm.js +1 -1
- package/dist/wu-framework.esm.js.map +1 -1
- package/dist/wu-framework.umd.js +1 -1
- package/dist/wu-framework.umd.js.map +1 -1
- package/package.json +10 -4
- package/src/adapters/react/index.js +73 -55
- 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 +29 -312
- package/src/ai/wu-ai-conversation.js +143 -84
- package/src/ai/wu-ai-orchestrate.js +1021 -0
- package/src/ai/wu-ai-provider.js +105 -10
- package/src/ai/wu-ai.js +338 -8
- package/src/core/wu-cache.js +1 -2
- package/src/core/wu-core.js +3 -4
- package/src/core/wu-mcp-bridge.js +198 -414
- package/src/core/wu-plugin.js +4 -1
- package/src/core/wu-style-bridge.js +23 -21
- package/src/index.js +25 -2
package/README.md
CHANGED
|
@@ -1,135 +1,144 @@
|
|
|
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
|
-
|
|
26
|
+
---
|
|
27
|
+
|
|
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.
|
|
4
29
|
|
|
5
|
-
|
|
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+.
|
|
6
31
|
|
|
7
32
|
```bash
|
|
8
33
|
npm install wu-framework
|
|
9
34
|
```
|
|
10
35
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## Why Wu?
|
|
14
|
-
|
|
15
|
-
Every microfrontend framework forces you to learn its language. Single-spa makes you export `bootstrap`, `mount`, `unmount`. Module Federation requires webpack config. Qiankun needs manual registration with lifecycle callbacks.
|
|
16
|
-
|
|
17
|
-
Wu doesn't. You write React code. You write Vue code. You write Angular code. Wu adapts to you.
|
|
18
|
-
|
|
19
|
-
```jsx
|
|
20
|
-
// That's it. Your React app is now a microfrontend.
|
|
21
|
-
wuReact.register('header', App);
|
|
22
|
-
```
|
|
36
|
+
## 30-Second Demo
|
|
23
37
|
|
|
24
|
-
|
|
38
|
+
```js
|
|
39
|
+
import { wu } from 'wu-framework';
|
|
40
|
+
import { wuReact } from 'wu-framework/adapters/react';
|
|
41
|
+
import { wuVue } from 'wu-framework/adapters/vue';
|
|
25
42
|
|
|
26
|
-
|
|
43
|
+
// Register micro-apps from different frameworks
|
|
44
|
+
wuReact.register('cart', CartApp);
|
|
45
|
+
wuVue.register('catalog', CatalogApp);
|
|
27
46
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
| **CSS isolation** | Manual | CSS prefixing (fragile) | None | **Shadow DOM + 3 configurable modes** |
|
|
32
|
-
| **JS isolation** | None | Basic Proxy | None | **Proxy sandbox with side-effect cleanup** |
|
|
33
|
-
| **Standalone mode** | No | No | No | **Automatic — works without shell** |
|
|
34
|
-
| **Framework API** | Generic | Generic | Generic | **Native hooks, composables, stores per framework** |
|
|
35
|
-
| **Prefetch** | Manual | Manual preload | None | **Speculation Rules API + fallbacks** |
|
|
36
|
-
| **QA Overrides** | None | None | None | **Cookie-based URL overrides (secure)** |
|
|
37
|
-
| **Config required** | Extensive | Moderate | Webpack plugin | **Zero** |
|
|
47
|
+
// Mount them — each gets its own Shadow DOM
|
|
48
|
+
await wu.mount('cart', '#cart-container');
|
|
49
|
+
await wu.mount('catalog', '#catalog-container');
|
|
38
50
|
|
|
39
|
-
|
|
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));
|
|
40
54
|
|
|
41
|
-
|
|
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),
|
|
61
|
+
});
|
|
42
62
|
|
|
43
|
-
|
|
63
|
+
// Now the AI can control your app
|
|
64
|
+
await wu.ai.send('Add product SKU-42 to the cart');
|
|
65
|
+
```
|
|
44
66
|
|
|
45
|
-
|
|
46
|
-
|-----------|-----------|-------------|
|
|
47
|
-
| **Topbar** | Preact | Store name, nav tabs, search, notifications, theme toggle |
|
|
48
|
-
| **Dashboard** | Svelte 5 | KPI cards, sparklines, recent orders, revenue chart |
|
|
49
|
-
| **Orders** | React | Order table with filters, search, status badges |
|
|
50
|
-
| **Products** | Vue 3 | Product catalog grid, stock badges, category filter |
|
|
51
|
-
| **Customers** | Solid.js | Customer list, segment badges, click-to-filter-orders |
|
|
52
|
-
| **Analytics** | Lit | Revenue bar chart, traffic donut, top products |
|
|
53
|
-
| **Chat** | Vanilla JS | Floating chat widget with conversations and messages |
|
|
54
|
-
| **Settings** | Angular 21 | Store config form, shipping zones, payment methods |
|
|
67
|
+
## Why Wu?
|
|
55
68
|
|
|
56
|
-
|
|
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 |
|
|
81
|
+
|
|
82
|
+
*Module Federation is Webpack-coupled; Wu is bundler-agnostic.
|
|
57
83
|
|
|
58
|
-
|
|
59
|
-
npm run dev # starts all 9 servers (1 shell + 8 micro-apps)
|
|
60
|
-
open http://localhost:4321
|
|
61
|
-
```
|
|
84
|
+
---
|
|
62
85
|
|
|
63
|
-
|
|
86
|
+
## Features
|
|
87
|
+
|
|
88
|
+
### Core
|
|
89
|
+
|
|
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
|
|
64
117
|
|
|
65
118
|
---
|
|
66
119
|
|
|
67
120
|
## Quick Start
|
|
68
121
|
|
|
69
|
-
### 1. Register your micro
|
|
122
|
+
### 1. Register your micro-app
|
|
70
123
|
|
|
71
|
-
**React:**
|
|
72
124
|
```jsx
|
|
125
|
+
// React
|
|
73
126
|
import { wuReact } from 'wu-framework/adapters/react';
|
|
74
|
-
import App from './App';
|
|
75
127
|
wuReact.register('orders', App);
|
|
76
|
-
```
|
|
77
128
|
|
|
78
|
-
|
|
79
|
-
```js
|
|
129
|
+
// Vue
|
|
80
130
|
import { wuVue } from 'wu-framework/adapters/vue';
|
|
81
|
-
import App from './App.vue';
|
|
82
131
|
wuVue.register('products', App);
|
|
83
|
-
```
|
|
84
132
|
|
|
85
|
-
|
|
86
|
-
```ts
|
|
87
|
-
import 'zone.js';
|
|
88
|
-
import '@angular/compiler';
|
|
89
|
-
import { createApplication } from '@angular/platform-browser';
|
|
90
|
-
import { createComponent, provideZoneChangeDetection } from '@angular/core';
|
|
133
|
+
// Angular (standalone)
|
|
91
134
|
import { wuAngular } from 'wu-framework/adapters/angular';
|
|
92
|
-
|
|
135
|
+
wuAngular.registerStandalone('settings', AppComponent, { createApplication, createComponent });
|
|
93
136
|
|
|
94
|
-
|
|
95
|
-
createApplication,
|
|
96
|
-
createComponent,
|
|
97
|
-
provideZoneChangeDetection,
|
|
98
|
-
});
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
**Svelte 5:**
|
|
102
|
-
```js
|
|
137
|
+
// Svelte 5
|
|
103
138
|
import { wuSvelte } from 'wu-framework/adapters/svelte';
|
|
104
|
-
import App from './App.svelte';
|
|
105
139
|
wuSvelte.registerSvelte5('dashboard', App);
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
**Solid:**
|
|
109
|
-
```jsx
|
|
110
|
-
import { wuSolid } from 'wu-framework/adapters/solid';
|
|
111
|
-
import App from './App';
|
|
112
|
-
wuSolid.register('customers', App);
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
**Preact:**
|
|
116
|
-
```jsx
|
|
117
|
-
import { wuPreact } from 'wu-framework/adapters/preact';
|
|
118
|
-
import App from './App';
|
|
119
|
-
wuPreact.register('topbar', App);
|
|
120
|
-
```
|
|
121
140
|
|
|
122
|
-
|
|
123
|
-
```js
|
|
124
|
-
import { wuLit } from 'wu-framework/adapters/lit';
|
|
125
|
-
import { MyApp } from './my-app.js';
|
|
126
|
-
wuLit.register('analytics', MyApp);
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
**Vanilla JS:**
|
|
130
|
-
```js
|
|
131
|
-
import wuVanilla from 'wu-framework/adapters/vanilla';
|
|
132
|
-
// use wuVanilla.useWuEvents() and wuVanilla.useWuStore() inside mount/unmount
|
|
141
|
+
// Same pattern for Solid, Preact, Lit, Vanilla
|
|
133
142
|
```
|
|
134
143
|
|
|
135
144
|
### 2. Mount from the shell
|
|
@@ -141,7 +150,7 @@ await wu.init({
|
|
|
141
150
|
apps: [
|
|
142
151
|
{ name: 'header', url: 'http://localhost:3001' },
|
|
143
152
|
{ name: 'sidebar', url: 'http://localhost:3002' },
|
|
144
|
-
{ name: 'content', url: 'http://localhost:3003' }
|
|
153
|
+
{ name: 'content', url: 'http://localhost:3003' },
|
|
145
154
|
]
|
|
146
155
|
});
|
|
147
156
|
|
|
@@ -150,568 +159,184 @@ await wu.mount('sidebar', '#sidebar-container');
|
|
|
150
159
|
await wu.mount('content', '#content-container');
|
|
151
160
|
```
|
|
152
161
|
|
|
153
|
-
|
|
162
|
+
### 3. Cross-app communication
|
|
154
163
|
|
|
155
|
-
|
|
164
|
+
```js
|
|
165
|
+
import { emit, on, getState, setState } from 'wu-framework';
|
|
156
166
|
|
|
157
|
-
|
|
167
|
+
// Events
|
|
168
|
+
emit('user:login', { userId: 123 });
|
|
169
|
+
on('user:*', (event) => console.log(event.data));
|
|
158
170
|
|
|
159
|
-
|
|
171
|
+
// Shared store
|
|
172
|
+
setState('user.name', 'John');
|
|
173
|
+
getState('user.name'); // 'John'
|
|
174
|
+
```
|
|
160
175
|
|
|
161
|
-
|
|
162
|
-
|-----------|---------|----------|-------------|
|
|
163
|
-
| React | `wuReact` | `.register(name, Component)` | `createUseWuEvents(React)`, `createUseWuStore(React)` |
|
|
164
|
-
| Vue 3 | `wuVue` | `.register(name, Component)` | `useWuEvents()`, `useWuStore()`, `WuSlot`, plugin |
|
|
165
|
-
| Angular 14+ | `wuAngular` | `.registerStandalone(name, Component, opts)` | `createWuService()` |
|
|
166
|
-
| Angular (NgModule) | `wuAngular` | `.register(name, Module)` | Same |
|
|
167
|
-
| Angular Elements | `wuAngular` | `.registerElement(name, Component)` | Same |
|
|
168
|
-
| Svelte 3/4 | `wuSvelte` | `.register(name, Component)` | `createWuStore()`, `useWuEvents()` |
|
|
169
|
-
| Svelte 5 | `wuSvelte` | `.registerSvelte5(name, Component)` | Same + `createWuEventStore()` |
|
|
170
|
-
| Preact | `wuPreact` | `.register(name, Component)` | `createUseWuEvents(hooks)`, `createUseWuStore(hooks)` |
|
|
171
|
-
| Preact (compat) | `wuPreact` | `.registerCompat(name, Component)` | Same |
|
|
172
|
-
| Solid.js | `wuSolid` | `.register(name, Component)` | `useWuEvents()`, `createWuStore()`, `createWuEvent()` |
|
|
173
|
-
| Lit | `wuLit` | `.register(name, Element)` | `WuMixin(LitElement)`, `wuProperty()` decorator |
|
|
174
|
-
| Web Component | `wuLit` | `.registerWebComponent(name, Element)` | Same |
|
|
175
|
-
| Vanilla JS | `wuVanilla` | `.register(name, config)` | `useWuEvents()`, `useWuStore()`, `createComponent()` |
|
|
176
|
-
| Vanilla (class) | `wuVanilla` | `.registerClass(name, Class)` | Same |
|
|
177
|
-
| Vanilla (template) | `wuVanilla` | `.registerTemplate(name, html)` | Same |
|
|
176
|
+
### 4. Add AI (optional)
|
|
178
177
|
|
|
179
|
-
|
|
178
|
+
```js
|
|
179
|
+
wu.ai.provider('ollama', {
|
|
180
|
+
endpoint: 'http://localhost:11434/api/chat',
|
|
181
|
+
model: 'llama3',
|
|
182
|
+
});
|
|
180
183
|
|
|
181
|
-
|
|
184
|
+
const response = await wu.ai.send('What apps are mounted?');
|
|
185
|
+
```
|
|
182
186
|
|
|
183
187
|
---
|
|
184
188
|
|
|
185
|
-
##
|
|
186
|
-
|
|
187
|
-
This is something no other microfrontend framework offers: **per-app configurable style isolation**.
|
|
188
|
-
|
|
189
|
-
| Mode | What happens | When to use |
|
|
190
|
-
|------|-------------|-------------|
|
|
191
|
-
| `shared` | Host document styles are injected into Shadow DOM | Apps sharing a design system (Tailwind, Element Plus) |
|
|
192
|
-
| `isolated` | Pure Shadow DOM — no external styles enter | Fully independent apps with their own CSS |
|
|
193
|
-
| `fully-isolated` | Only the app's own styles are injected | Apps that need their CSS but not global CSS |
|
|
189
|
+
## WuCommerce — Real-World Example
|
|
194
190
|
|
|
195
|
-
|
|
191
|
+
Wu ships with **WuCommerce**, a Shopify-like merchant dashboard where every section is a real micro-app built with a different framework.
|
|
196
192
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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 |
|
|
204
203
|
|
|
205
|
-
|
|
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.
|
|
206
205
|
|
|
207
206
|
---
|
|
208
207
|
|
|
209
|
-
##
|
|
210
|
-
|
|
211
|
-
Wu offers three sandbox modes. Pick the one that fits your workflow:
|
|
208
|
+
## 3 Sandbox Strategies
|
|
212
209
|
|
|
213
210
|
| Mode | How it works | Tree shaking | Source maps | HMR | JS isolation |
|
|
214
211
|
|------|-------------|:---:|:---:|:---:|:---:|
|
|
215
|
-
| `module` (default) | `import()` + Proxy side-effect tracking |
|
|
216
|
-
| `strict` | Hidden iframe + real `import()` |
|
|
217
|
-
| `eval` | Fetch HTML → parse → `with(proxy){}` |
|
|
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) |
|
|
218
215
|
|
|
219
216
|
```js
|
|
220
|
-
// Global setting
|
|
221
|
-
await wu.init({
|
|
222
|
-
sandbox: 'strict', // or 'module' (default) or 'eval'
|
|
223
|
-
apps: [...]
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
// Per-app override — mix modes in the same page
|
|
227
217
|
await wu.init({
|
|
228
218
|
apps: [
|
|
229
|
-
{ name: 'header', url: '...', sandbox: 'module' },
|
|
230
|
-
{ name: 'analytics', url: '...', sandbox: 'strict' },
|
|
231
|
-
{ name: 'legacy', url: '...', sandbox: 'eval' },
|
|
219
|
+
{ name: 'header', url: '...', sandbox: 'module' },
|
|
220
|
+
{ name: 'analytics', url: '...', sandbox: 'strict' },
|
|
221
|
+
{ name: 'legacy', url: '...', sandbox: 'eval' },
|
|
232
222
|
]
|
|
233
223
|
});
|
|
234
224
|
```
|
|
235
225
|
|
|
236
|
-
**
|
|
226
|
+
**Auto-cleaned on unmount:** timers, intervals, rAF, event listeners, localStorage keys, DOM mutations.
|
|
237
227
|
|
|
238
|
-
|
|
228
|
+
---
|
|
239
229
|
|
|
240
|
-
|
|
230
|
+
## 3 CSS Isolation Modes
|
|
241
231
|
|
|
242
|
-
|
|
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 |
|
|
243
237
|
|
|
238
|
+
```json
|
|
239
|
+
{ "name": "my-app", "entry": "index.js", "styleMode": "isolated" }
|
|
244
240
|
```
|
|
245
|
-
┌── Main Window ──────────────────────────────────┐
|
|
246
|
-
│ ┌── Shadow DOM ──────────────────────────────┐ │
|
|
247
|
-
│ │ App renders here (CSS isolated) │ │
|
|
248
|
-
│ │ document.querySelector → scoped here │ │
|
|
249
|
-
│ └────────────────────────────────────────────┘ │
|
|
250
|
-
│ ┌── Hidden iframe ──────────────────────────┐ │
|
|
251
|
-
│ │ import() runs here (REAL ES modules) │ │
|
|
252
|
-
│ │ window = separate context (ISOLATED) │ │
|
|
253
|
-
│ │ document.createElement → main document │ │
|
|
254
|
-
│ │ Destroy iframe = kill everything │ │
|
|
255
|
-
│ └────────────────────────────────────────────┘ │
|
|
256
|
-
└──────────────────────────────────────────────────┘
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
Strict mode preserves your entire development workflow:
|
|
260
|
-
- **Tree shaking** — real `import()`, bundler optimizations work as normal
|
|
261
|
-
- **Source maps** — browser loads real modules, maps resolve correctly
|
|
262
|
-
- **Vite HMR** — HMR client runs inside iframe, WebSocket connects to dev server
|
|
263
|
-
- **Full isolation** — separate `window` context, no global leaks between apps
|
|
264
|
-
|
|
265
|
-
**What gets tracked and auto-cleaned (all modes):**
|
|
266
|
-
- `setTimeout` / `setInterval` / `requestAnimationFrame` — all IDs tracked, all cleared
|
|
267
|
-
- `addEventListener` / `removeEventListener` — all listeners tracked, all removed
|
|
268
|
-
- `document.querySelector` — scoped to the app's Shadow DOM
|
|
269
|
-
- `localStorage` / `sessionStorage` — keys prefixed with `wu_{appName}_`
|
|
270
|
-
|
|
271
|
-
**277 tests verify this works.** Unit tests for every isolation feature, integration tests proving two sandboxes don't contaminate each other.
|
|
272
241
|
|
|
273
242
|
---
|
|
274
243
|
|
|
275
|
-
##
|
|
244
|
+
## AI Paradigms
|
|
276
245
|
|
|
277
|
-
###
|
|
246
|
+
### 1. App → LLM → App
|
|
278
247
|
|
|
279
248
|
```js
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
emit('user:login', { userId: 123 });
|
|
283
|
-
|
|
284
|
-
const unsub = on('user:*', (event) => {
|
|
285
|
-
console.log(event.name, event.data);
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
once('app:ready', (e) => console.log('Ready'));
|
|
289
|
-
unsub();
|
|
249
|
+
const response = await wu.ai.send('What items are in the cart?');
|
|
290
250
|
```
|
|
291
251
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
### Store
|
|
252
|
+
### 2. LLM → App → LLM (WebMCP)
|
|
295
253
|
|
|
296
254
|
```js
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
setState('user.name', 'John');
|
|
300
|
-
setState('user.preferences.theme', 'dark');
|
|
301
|
-
|
|
302
|
-
getState('user.name'); // 'John'
|
|
303
|
-
|
|
304
|
-
const unsub = onStateChange('user.*', (value, path) => {
|
|
305
|
-
console.log(`${path} = ${value}`);
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
// Batch updates
|
|
309
|
-
wu.store.batch({ 'cart.count': 5, 'cart.total': 99.99 });
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
Ring buffer event history. Wildcard subscriptions. Dot-notation paths with auto-creation of nested objects.
|
|
313
|
-
|
|
314
|
-
---
|
|
315
|
-
|
|
316
|
-
## Framework-Native Integration Examples
|
|
317
|
-
|
|
318
|
-
> All examples below are from **WuCommerce**, a real merchant dashboard built with Wu Framework.
|
|
319
|
-
> 8 micro-apps, 8 different frameworks, running together in one shell.
|
|
320
|
-
> See `examples/astro-multi-framework/` for the full source.
|
|
321
|
-
|
|
322
|
-
### React — Orders (mf-eventlab)
|
|
323
|
-
|
|
324
|
-
```jsx
|
|
325
|
-
// main.jsx
|
|
326
|
-
import { wuReact } from 'wu-framework/adapters/react';
|
|
327
|
-
import App from './App';
|
|
328
|
-
wuReact.register('orders', App);
|
|
329
|
-
|
|
330
|
-
// App.jsx — hooks are factories, pass React to get the hook
|
|
331
|
-
import React, { useState, useEffect, useMemo } from 'react';
|
|
332
|
-
import { createUseWuEvents, createUseWuStore } from 'wu-framework/adapters/react';
|
|
333
|
-
|
|
334
|
-
const useWuEvents = createUseWuEvents(React);
|
|
335
|
-
const useWuStore = createUseWuStore(React);
|
|
336
|
-
|
|
337
|
-
function Orders() {
|
|
338
|
-
const { emit, on } = useWuEvents();
|
|
339
|
-
const [filter, setFilter] = useState('all');
|
|
340
|
-
|
|
341
|
-
useEffect(() => {
|
|
342
|
-
const unsub = on('customer:selected', (e) => {
|
|
343
|
-
setFilter(e.data?.customerName || 'all');
|
|
344
|
-
});
|
|
345
|
-
return unsub;
|
|
346
|
-
}, []);
|
|
347
|
-
|
|
348
|
-
return <button onClick={() => emit('order:new', { id: 1001, total: 49.99 })}>New Order</button>;
|
|
349
|
-
}
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
### Vue 3 — Products (mf-statebridge)
|
|
353
|
-
|
|
354
|
-
```vue
|
|
355
|
-
<!-- main.js -->
|
|
356
|
-
<!-- import { wuVue } from 'wu-framework/adapters/vue'; -->
|
|
357
|
-
<!-- import App from './App.vue'; -->
|
|
358
|
-
<!-- wuVue.register('products', App); -->
|
|
359
|
-
|
|
360
|
-
<script setup>
|
|
361
|
-
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
|
362
|
-
import { wuVue } from 'wu-framework/adapters/vue';
|
|
363
|
-
|
|
364
|
-
const { useWuEvents, useWuStore } = wuVue;
|
|
365
|
-
const events = useWuEvents();
|
|
366
|
-
|
|
367
|
-
onMounted(() => {
|
|
368
|
-
events.on('search:global', (e) => {
|
|
369
|
-
search.value = e.data?.query || '';
|
|
370
|
-
});
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
function handleStockAlert(product) {
|
|
374
|
-
events.emit('product:stockAlert', { productId: product.id, stock: product.stock });
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
onUnmounted(() => events.cleanup());
|
|
378
|
-
</script>
|
|
255
|
+
wu.ai.expose(); // Registers all tools via navigator.modelContext (Chrome 146+)
|
|
379
256
|
```
|
|
380
257
|
|
|
381
|
-
###
|
|
382
|
-
|
|
383
|
-
```svelte
|
|
384
|
-
<!-- main.js: wuSvelte.registerSvelte5('dashboard', App) -->
|
|
385
|
-
<script>
|
|
386
|
-
import { wuSvelte } from 'wu-framework/adapters/svelte';
|
|
387
|
-
|
|
388
|
-
const { createWuStore, createWuEventStore, useWuEvents } = wuSvelte;
|
|
389
|
-
const { emit, on, cleanup } = useWuEvents();
|
|
390
|
-
|
|
391
|
-
let stats = $state({ revenue: 12847, orders: 156, visitors: 2341, conversion: 4.2 });
|
|
392
|
-
|
|
393
|
-
on('theme:toggle', (e) => console.log('Theme:', e.data?.theme));
|
|
394
|
-
|
|
395
|
-
function handleNewOrder() {
|
|
396
|
-
emit('order:new', { orderId: `ORD-${Date.now()}`, total: 49.99, status: 'pending' });
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// cleanup is called automatically on component destroy
|
|
400
|
-
</script>
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
### Solid.js — Customers (mf-features)
|
|
404
|
-
|
|
405
|
-
```jsx
|
|
406
|
-
// main.jsx: wuSolid.register('customers', App)
|
|
407
|
-
import { createSignal, onMount } from 'solid-js';
|
|
408
|
-
import { wuSolid } from 'wu-framework/adapters/solid';
|
|
409
|
-
|
|
410
|
-
export default function Customers() {
|
|
411
|
-
const [search, setSearch] = createSignal('');
|
|
412
|
-
const { emit, on } = wuSolid.useWuEvents(); // auto-cleanup via onCleanup
|
|
413
|
-
|
|
414
|
-
onMount(() => {
|
|
415
|
-
on('search:global', (e) => setSearch(e.data?.query || ''));
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
const handleRowClick = (customer) => {
|
|
419
|
-
emit('customer:selected', { customerId: customer.id, customerName: customer.name });
|
|
420
|
-
emit('nav:section', { section: 'orders' });
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
return <div>...</div>;
|
|
424
|
-
}
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
### Preact — Topbar (mf-header)
|
|
428
|
-
|
|
429
|
-
```jsx
|
|
430
|
-
// main.jsx: wuPreact.register('topbar', App)
|
|
431
|
-
import { useState, useCallback, useEffect, useRef } from 'preact/hooks';
|
|
432
|
-
import { wuPreact } from 'wu-framework/adapters/preact';
|
|
433
|
-
|
|
434
|
-
// Factory pattern — pass hooks as argument
|
|
435
|
-
const useWuEvents = wuPreact.createUseWuEvents({ useCallback, useEffect, useRef });
|
|
436
|
-
const useWuStore = wuPreact.createUseWuStore({ useState, useCallback, useEffect });
|
|
437
|
-
|
|
438
|
-
function Topbar() {
|
|
439
|
-
const { emit, on } = useWuEvents();
|
|
440
|
-
const storeData = useWuStore('store');
|
|
441
|
-
|
|
442
|
-
const handleSearch = (query) => emit('search:global', { query });
|
|
443
|
-
const toggleTheme = () => emit('theme:toggle', { theme: isDark ? 'light' : 'dark' });
|
|
444
|
-
|
|
445
|
-
return <header>...</header>;
|
|
446
|
-
}
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
### Angular 21 — Settings (mf-pluginperf)
|
|
450
|
-
|
|
451
|
-
```ts
|
|
452
|
-
// main.ts — full setup (JIT mode, no AnalogJS needed)
|
|
453
|
-
import 'zone.js';
|
|
454
|
-
import '@angular/compiler';
|
|
455
|
-
import { createApplication } from '@angular/platform-browser';
|
|
456
|
-
import { createComponent, provideZoneChangeDetection } from '@angular/core';
|
|
457
|
-
import { wuAngular } from 'wu-framework/adapters/angular';
|
|
458
|
-
import { SettingsComponent } from './app/settings.component';
|
|
459
|
-
|
|
460
|
-
wuAngular.registerStandalone('settings', SettingsComponent, {
|
|
461
|
-
standaloneContainer: '#app',
|
|
462
|
-
createApplication, // pass Angular APIs to avoid bundler issues
|
|
463
|
-
createComponent,
|
|
464
|
-
provideZoneChangeDetection,
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
// settings.component.ts — use createWuService for events/store
|
|
468
|
-
import { Component, OnInit, OnDestroy } from '@angular/core';
|
|
469
|
-
import { createWuService } from 'wu-framework/adapters/angular';
|
|
470
|
-
|
|
471
|
-
@Component({ selector: 'app-settings', standalone: true, template: '...' })
|
|
472
|
-
export class SettingsComponent implements OnInit, OnDestroy {
|
|
473
|
-
private wu = createWuService();
|
|
474
|
-
storeName = '';
|
|
475
|
-
|
|
476
|
-
ngOnInit() {
|
|
477
|
-
this.storeName = this.wu.getState('store')?.name || '';
|
|
478
|
-
this.wu.on('theme:toggle', (e) => console.log('Theme:', e.data?.theme));
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
save() {
|
|
482
|
-
this.wu.setState('store', { name: this.storeName });
|
|
483
|
-
this.wu.emit('settings:saved', { name: this.storeName });
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
ngOnDestroy() { this.wu.destroy(); }
|
|
487
|
-
}
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
> **Angular + Vite setup:** No AnalogJS or Angular CLI required. Plain Vite with
|
|
491
|
-
> `esbuild: { target: 'es2022' }` and `tsconfig.json` with `experimentalDecorators: true`.
|
|
492
|
-
> `@angular/compiler` import enables JIT mode at runtime. Pass `createApplication`,
|
|
493
|
-
> `createComponent`, `provideZoneChangeDetection` as options to `registerStandalone`
|
|
494
|
-
> so the bundler resolves them from your app's `node_modules`.
|
|
495
|
-
|
|
496
|
-
### Lit — Analytics (mf-showcase)
|
|
258
|
+
### 3. Autonomous Agent
|
|
497
259
|
|
|
498
260
|
```js
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
import { WuMixin } from 'wu-framework/adapters/lit';
|
|
502
|
-
|
|
503
|
-
class AnalyticsApp extends WuMixin(LitElement) {
|
|
504
|
-
static styles = css`...`;
|
|
505
|
-
|
|
506
|
-
connectedCallback() {
|
|
507
|
-
super.connectedCallback();
|
|
508
|
-
this.wuOn('theme:toggle', () => this.requestUpdate());
|
|
509
|
-
const stats = this.wuGetState('stats');
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
render() {
|
|
513
|
-
return html`
|
|
514
|
-
<button @click=${() => this.wuEmit('analytics:export')}>Export</button>
|
|
515
|
-
`;
|
|
516
|
-
}
|
|
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}`);
|
|
517
263
|
}
|
|
518
|
-
customElements.define('analytics-app', AnalyticsApp);
|
|
519
264
|
```
|
|
520
265
|
|
|
521
|
-
###
|
|
266
|
+
### 4. Cross-App Orchestration
|
|
522
267
|
|
|
523
268
|
```js
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
const { useWuEvents, useWuStore } = wuVanilla;
|
|
528
|
-
const events = useWuEvents();
|
|
529
|
-
const store = useWuStore();
|
|
530
|
-
|
|
531
|
-
function mount(container) {
|
|
532
|
-
events.on('theme:toggle', (e) => applyTheme(e.data?.theme));
|
|
533
|
-
const user = store.get('user');
|
|
534
|
-
// render chat UI into container...
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
function unmount(container) {
|
|
538
|
-
events.cleanup();
|
|
539
|
-
container.innerHTML = '';
|
|
540
|
-
}
|
|
269
|
+
const result = await wu.ai.intent('Find customer Emma and refund order #4821');
|
|
270
|
+
console.log(result.appsInvolved); // ['customers', 'orders']
|
|
541
271
|
```
|
|
542
272
|
|
|
543
273
|
---
|
|
544
274
|
|
|
545
|
-
## Plugins &
|
|
275
|
+
## Plugins & Hooks
|
|
546
276
|
|
|
547
277
|
```js
|
|
548
|
-
import { usePlugin, createPlugin, useHook
|
|
278
|
+
import { usePlugin, createPlugin, useHook } from 'wu-framework';
|
|
549
279
|
|
|
550
|
-
// Plugin
|
|
551
280
|
usePlugin(createPlugin({
|
|
552
281
|
name: 'analytics',
|
|
553
282
|
install: (api) => api.on('app:mounted', (e) => track(e)),
|
|
554
283
|
afterMount: async (ctx) => log('mounted in', ctx.mountTime, 'ms')
|
|
555
284
|
}));
|
|
556
285
|
|
|
557
|
-
// Lifecycle hook
|
|
558
286
|
useHook('beforeMount', async (context, next) => {
|
|
559
287
|
console.log('Mounting:', context.appName);
|
|
560
288
|
await next();
|
|
561
289
|
});
|
|
562
|
-
|
|
563
|
-
// Guard — can cancel mount
|
|
564
|
-
useHook('beforeMount', createGuardHook(async () => isAuthenticated()));
|
|
565
290
|
```
|
|
566
291
|
|
|
567
292
|
Phases: `beforeInit` → `afterInit` → `beforeLoad` → `afterLoad` → `beforeMount` → `afterMount` → `beforeUnmount` → `afterUnmount`
|
|
568
293
|
|
|
569
294
|
---
|
|
570
295
|
|
|
571
|
-
##
|
|
572
|
-
|
|
573
|
-
```js
|
|
574
|
-
await wu.init({
|
|
575
|
-
apps: [
|
|
576
|
-
{ name: 'header', url: '/mfe/header', strategy: 'eager' },
|
|
577
|
-
{ name: 'content', url: '/mfe/content', strategy: 'lazy' },
|
|
578
|
-
{ name: 'analytics', url: '/mfe/analytics', strategy: 'idle' }
|
|
579
|
-
]
|
|
580
|
-
});
|
|
581
|
-
```
|
|
582
|
-
|
|
583
|
-
| Strategy | Behavior |
|
|
584
|
-
|----------|----------|
|
|
585
|
-
| `lazy` | Load when mounted (default) |
|
|
586
|
-
| `eager` | Load immediately |
|
|
587
|
-
| `preload` | `<link rel="prefetch">` |
|
|
588
|
-
| `idle` | `requestIdleCallback` |
|
|
589
|
-
| `speculate` | Speculation Rules API with automatic fallback chain |
|
|
590
|
-
|
|
591
|
-
---
|
|
592
|
-
|
|
593
|
-
## Intelligent Prefetch (Speculation Rules API)
|
|
594
|
-
|
|
595
|
-
Wu uses the browser-native [Speculation Rules API](https://developer.chrome.com/docs/web-platform/prerender-pages) (Chrome 121+) for near-instant microfrontend loads, with automatic fallbacks for older browsers.
|
|
596
|
-
|
|
597
|
-
### Fallback chain
|
|
598
|
-
|
|
599
|
-
```
|
|
600
|
-
Speculation Rules API → <link rel="modulepreload"> → <link rel="prefetch">
|
|
601
|
-
(Chrome 121+) (modern browsers) (all browsers)
|
|
602
|
-
```
|
|
603
|
-
|
|
604
|
-
### Usage
|
|
296
|
+
## Prefetch (Speculation Rules API)
|
|
605
297
|
|
|
606
298
|
```js
|
|
607
|
-
// Prefetch specific apps
|
|
608
299
|
wu.prefetch(['sidebar', 'analytics']);
|
|
609
|
-
|
|
610
|
-
// Prefetch all registered apps
|
|
300
|
+
wu.prefetch(['sidebar'], { trigger: 'hover', action: 'prerender' });
|
|
611
301
|
wu.prefetchAll();
|
|
612
|
-
|
|
613
|
-
// With options
|
|
614
|
-
wu.prefetch(['sidebar'], {
|
|
615
|
-
trigger: 'hover', // 'immediate' | 'hover' | 'visible' | 'idle'
|
|
616
|
-
action: 'prefetch', // 'prefetch' | 'prerender'
|
|
617
|
-
eagerness: 'moderate', // 'immediate' | 'eager' | 'moderate' | 'conservative'
|
|
618
|
-
});
|
|
619
302
|
```
|
|
620
303
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
| Trigger | Behavior |
|
|
624
|
-
|---------|----------|
|
|
625
|
-
| `immediate` | Prefetch now (default) |
|
|
626
|
-
| `hover` | Prefetch when user hovers over the app's container |
|
|
627
|
-
| `visible` | Prefetch when app's container enters viewport (IntersectionObserver, 200px margin) |
|
|
628
|
-
| `idle` | Prefetch during browser idle time (`requestIdleCallback`) |
|
|
629
|
-
|
|
630
|
-
### As loading strategy
|
|
631
|
-
|
|
632
|
-
```js
|
|
633
|
-
await wu.init({
|
|
634
|
-
apps: [
|
|
635
|
-
{ name: 'header', url: '/mfe/header', strategy: 'eager' },
|
|
636
|
-
{ name: 'sidebar', url: '/mfe/sidebar', strategy: 'speculate' },
|
|
637
|
-
{ name: 'analytics', url: '/mfe/analytics', strategy: 'idle' },
|
|
638
|
-
]
|
|
639
|
-
});
|
|
640
|
-
```
|
|
641
|
-
|
|
642
|
-
The `speculate` strategy uses the Speculation Rules API by default with `immediate` trigger. It degrades gracefully — your app works on any browser, it just loads faster on Chrome 121+.
|
|
304
|
+
Fallback chain: Speculation Rules API (Chrome 121+) → `<link rel="modulepreload">` → `<link rel="prefetch">`
|
|
643
305
|
|
|
644
306
|
---
|
|
645
307
|
|
|
646
|
-
## Cookie Overrides for QA
|
|
647
|
-
|
|
648
|
-
Redirect individual microfrontends to different URLs without changing code or deploying. QA sets a cookie, and only **their browser** sees the override — everyone else sees production.
|
|
649
|
-
|
|
650
|
-
### How it works
|
|
651
|
-
|
|
652
|
-
```
|
|
653
|
-
1. QA opens DevTools → Application → Cookies
|
|
654
|
-
2. Sets: wu-override:sidebar=http://localhost:5174
|
|
655
|
-
3. Reloads → only "sidebar" loads from localhost
|
|
656
|
-
4. Everyone else sees production sidebar
|
|
657
|
-
```
|
|
658
|
-
|
|
659
|
-
### Programmatic API
|
|
308
|
+
## Cookie Overrides for QA
|
|
660
309
|
|
|
661
310
|
```js
|
|
662
|
-
// Set an override (persists as cookie for 24h)
|
|
663
311
|
wu.override('sidebar', 'http://localhost:5174');
|
|
664
|
-
|
|
665
|
-
// Check active overrides
|
|
666
|
-
wu.getOverrides();
|
|
667
|
-
// → { sidebar: 'http://localhost:5174' }
|
|
668
|
-
|
|
669
|
-
// Remove one
|
|
312
|
+
wu.getOverrides(); // { sidebar: 'http://localhost:5174' }
|
|
670
313
|
wu.removeOverride('sidebar');
|
|
671
|
-
|
|
672
|
-
// Clear all
|
|
673
|
-
wu.clearOverrides();
|
|
674
314
|
```
|
|
675
315
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
| Layer | Protection |
|
|
679
|
-
|-------|-----------|
|
|
680
|
-
| **Environment gate** | Disabled in production by default. Auto-enabled only on `localhost` / `127.0.0.1`. Must explicitly opt-in for production. |
|
|
681
|
-
| **Domain allowlist** | Only overrides to whitelisted domains are accepted. Supports wildcards: `*.company.com`. |
|
|
682
|
-
| **Visual indicator** | Fixed yellow banner shows active overrides. Prevents silent phishing. Click to hide, double-click to clear. |
|
|
683
|
-
|
|
684
|
-
### Enable in production (for QA teams)
|
|
685
|
-
|
|
686
|
-
```js
|
|
687
|
-
wu.overrides.configure({
|
|
688
|
-
enabled: true,
|
|
689
|
-
allowedDomains: ['*.mycompany.com', 'localhost', '*.vercel.app'],
|
|
690
|
-
showIndicator: true,
|
|
691
|
-
});
|
|
692
|
-
```
|
|
316
|
+
QA sets a cookie → only **their browser** sees the override. Everyone else sees production. 3-layer security: environment gate, domain allowlist, visual indicator.
|
|
693
317
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
```
|
|
697
|
-
wu-override:<appName>=<url>
|
|
318
|
+
---
|
|
698
319
|
|
|
699
|
-
|
|
700
|
-
wu-override:sidebar=http://localhost:5174
|
|
701
|
-
wu-override:header=https://staging.mycompany.com/header
|
|
702
|
-
```
|
|
320
|
+
## Project Stats
|
|
703
321
|
|
|
704
|
-
|
|
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 |
|
|
705
332
|
|
|
706
333
|
---
|
|
707
334
|
|
|
708
|
-
## Build
|
|
335
|
+
## Build
|
|
709
336
|
|
|
710
337
|
```bash
|
|
711
338
|
npm run build # ESM + CJS + UMD + Dev
|
|
712
|
-
npm run
|
|
713
|
-
npm run build:dev # Development (unminified)
|
|
714
|
-
npm run test # 277 tests (Vitest)
|
|
339
|
+
npm run test # 650 tests (Vitest)
|
|
715
340
|
npm run test:coverage # Coverage report
|
|
716
341
|
```
|
|
717
342
|
|
|
@@ -728,80 +353,56 @@ npm run test:coverage # Coverage report
|
|
|
728
353
|
|
|
729
354
|
```
|
|
730
355
|
┌───────────────────────────────────────────────────────────────────────┐
|
|
731
|
-
│ SHELL (
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
│
|
|
735
|
-
│
|
|
736
|
-
│ │
|
|
737
|
-
│
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
│
|
|
741
|
-
│
|
|
742
|
-
│
|
|
743
|
-
|
|
744
|
-
|
|
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
|
+
└──────────────────────────────────────────────────────────────────────┘
|
|
745
373
|
```
|
|
746
374
|
|
|
747
|
-
Each micro-app runs inside its own Shadow DOM with configurable CSS isolation and a JS sandbox that tracks and auto-cleans all side effects on unmount.
|
|
748
|
-
|
|
749
375
|
---
|
|
750
376
|
|
|
751
|
-
##
|
|
752
|
-
|
|
753
|
-
```js
|
|
754
|
-
// Core
|
|
755
|
-
import { wu, init, mount, unmount, destroy, app, define } from 'wu-framework';
|
|
756
|
-
|
|
757
|
-
// Events
|
|
758
|
-
import { emit, on, once, off } from 'wu-framework';
|
|
377
|
+
## Documentation
|
|
759
378
|
|
|
760
|
-
|
|
761
|
-
import { getState, setState, onStateChange } from 'wu-framework';
|
|
379
|
+
Full documentation at **[wu-framework.dev](https://wu-framework.dev)**
|
|
762
380
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
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
|
|
766
393
|
|
|
767
|
-
|
|
768
|
-
import { startMeasure, endMeasure, generatePerformanceReport } from 'wu-framework';
|
|
394
|
+
---
|
|
769
395
|
|
|
770
|
-
|
|
771
|
-
import { prefetch, prefetchAll } from 'wu-framework';
|
|
396
|
+
## Browser Support
|
|
772
397
|
|
|
773
|
-
|
|
774
|
-
import { override, removeOverride, getOverrides, clearOverrides } from 'wu-framework';
|
|
398
|
+
Chrome 80+, Firefox 78+, Safari 14+, Edge 80+. Shadow DOM v1 required.
|
|
775
399
|
|
|
776
|
-
|
|
777
|
-
import { wuReact } from 'wu-framework/adapters/react';
|
|
778
|
-
import { wuVue } from 'wu-framework/adapters/vue';
|
|
779
|
-
import { wuAngular } from 'wu-framework/adapters/angular';
|
|
780
|
-
import { wuSvelte } from 'wu-framework/adapters/svelte';
|
|
781
|
-
import { wuPreact } from 'wu-framework/adapters/preact';
|
|
782
|
-
import { wuSolid } from 'wu-framework/adapters/solid';
|
|
783
|
-
import { wuLit } from 'wu-framework/adapters/lit';
|
|
784
|
-
import { wuVanilla } from 'wu-framework/adapters/vanilla';
|
|
400
|
+
## Contributing
|
|
785
401
|
|
|
786
|
-
|
|
787
|
-
wu.prefetch(['sidebar', 'analytics']);
|
|
788
|
-
wu.prefetch(['sidebar'], { trigger: 'hover' });
|
|
789
|
-
wu.prefetchAll();
|
|
790
|
-
|
|
791
|
-
// Overrides (QA)
|
|
792
|
-
wu.override('sidebar', 'http://localhost:5174');
|
|
793
|
-
wu.removeOverride('sidebar');
|
|
794
|
-
wu.getOverrides();
|
|
795
|
-
wu.clearOverrides();
|
|
796
|
-
wu.overrides.configure({ enabled: true, allowedDomains: ['*.company.com'] });
|
|
797
|
-
|
|
798
|
-
// Log control
|
|
799
|
-
wu.silence();
|
|
800
|
-
wu.verbose();
|
|
801
|
-
```
|
|
802
|
-
|
|
803
|
-
---
|
|
402
|
+
Contributions welcome. Please open an issue first to discuss what you'd like to change.
|
|
804
403
|
|
|
805
404
|
## License
|
|
806
405
|
|
|
807
|
-
MIT
|
|
406
|
+
[MIT](./LICENSE) — Free for personal and commercial use.
|
|
407
|
+
|
|
408
|
+
See [LICENSE-COMMERCIAL.md](./LICENSE-COMMERCIAL.md) for optional enterprise support and consulting.
|