wu-framework 1.1.15 → 1.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +52 -20
  2. package/dist/wu-framework.cjs.js +1 -1
  3. package/dist/wu-framework.cjs.js.map +1 -1
  4. package/dist/wu-framework.dev.js +15511 -15146
  5. package/dist/wu-framework.dev.js.map +1 -1
  6. package/dist/wu-framework.esm.js +1 -1
  7. package/dist/wu-framework.esm.js.map +1 -1
  8. package/dist/wu-framework.umd.js +1 -1
  9. package/dist/wu-framework.umd.js.map +1 -1
  10. package/package.json +166 -161
  11. package/src/adapters/angular/ai.js +30 -30
  12. package/src/adapters/angular/index.d.ts +154 -154
  13. package/src/adapters/angular/index.js +932 -932
  14. package/src/adapters/angular.d.ts +3 -3
  15. package/src/adapters/angular.js +3 -3
  16. package/src/adapters/index.js +168 -168
  17. package/src/adapters/lit/ai.js +20 -20
  18. package/src/adapters/lit/index.d.ts +120 -120
  19. package/src/adapters/lit/index.js +721 -721
  20. package/src/adapters/lit.d.ts +3 -3
  21. package/src/adapters/lit.js +3 -3
  22. package/src/adapters/preact/ai.js +33 -33
  23. package/src/adapters/preact/index.d.ts +108 -108
  24. package/src/adapters/preact/index.js +661 -661
  25. package/src/adapters/preact.d.ts +3 -3
  26. package/src/adapters/preact.js +3 -3
  27. package/src/adapters/react/index.js +48 -54
  28. package/src/adapters/react.d.ts +3 -3
  29. package/src/adapters/react.js +3 -3
  30. package/src/adapters/shared.js +64 -64
  31. package/src/adapters/solid/ai.js +32 -32
  32. package/src/adapters/solid/index.d.ts +101 -101
  33. package/src/adapters/solid/index.js +586 -586
  34. package/src/adapters/solid.d.ts +3 -3
  35. package/src/adapters/solid.js +3 -3
  36. package/src/adapters/svelte/ai.js +31 -31
  37. package/src/adapters/svelte/index.d.ts +166 -166
  38. package/src/adapters/svelte/index.js +798 -798
  39. package/src/adapters/svelte.d.ts +3 -3
  40. package/src/adapters/svelte.js +3 -3
  41. package/src/adapters/vanilla/ai.js +30 -30
  42. package/src/adapters/vanilla/index.d.ts +179 -179
  43. package/src/adapters/vanilla/index.js +785 -785
  44. package/src/adapters/vanilla.d.ts +3 -3
  45. package/src/adapters/vanilla.js +3 -3
  46. package/src/adapters/vue/ai.js +52 -52
  47. package/src/adapters/vue/index.d.ts +299 -299
  48. package/src/adapters/vue/index.js +610 -610
  49. package/src/adapters/vue.d.ts +3 -3
  50. package/src/adapters/vue.js +3 -3
  51. package/src/ai/wu-ai-actions.js +261 -261
  52. package/src/ai/wu-ai-agent.js +546 -546
  53. package/src/ai/wu-ai-browser-primitives.js +354 -354
  54. package/src/ai/wu-ai-browser.js +380 -380
  55. package/src/ai/wu-ai-context.js +332 -332
  56. package/src/ai/wu-ai-conversation.js +613 -613
  57. package/src/ai/wu-ai-orchestrate.js +1021 -1021
  58. package/src/ai/wu-ai-permissions.js +381 -381
  59. package/src/ai/wu-ai-provider.js +700 -700
  60. package/src/ai/wu-ai-schema.js +225 -225
  61. package/src/ai/wu-ai-triggers.js +396 -396
  62. package/src/ai/wu-ai.js +804 -804
  63. package/src/core/wu-app.js +236 -236
  64. package/src/core/wu-cache.js +498 -477
  65. package/src/core/wu-core.js +1412 -1398
  66. package/src/core/wu-error-boundary.js +396 -382
  67. package/src/core/wu-event-bus.js +390 -348
  68. package/src/core/wu-hooks.js +350 -350
  69. package/src/core/wu-html-parser.js +199 -190
  70. package/src/core/wu-iframe-sandbox.js +328 -328
  71. package/src/core/wu-loader.js +385 -273
  72. package/src/core/wu-logger.js +142 -134
  73. package/src/core/wu-manifest.js +532 -509
  74. package/src/core/wu-mcp-bridge.js +432 -432
  75. package/src/core/wu-overrides.js +510 -510
  76. package/src/core/wu-performance.js +228 -228
  77. package/src/core/wu-plugin.js +401 -348
  78. package/src/core/wu-prefetch.js +414 -414
  79. package/src/core/wu-proxy-sandbox.js +477 -476
  80. package/src/core/wu-sandbox.js +779 -779
  81. package/src/core/wu-script-executor.js +161 -113
  82. package/src/core/wu-snapshot-sandbox.js +227 -227
  83. package/src/core/wu-store.js +13 -3
  84. package/src/core/wu-strategies.js +256 -256
  85. package/src/core/wu-style-bridge.js +477 -477
  86. package/src/index.d.ts +317 -0
  87. package/src/index.js +234 -224
  88. package/src/utils/dependency-resolver.js +327 -327
@@ -1,190 +1,199 @@
1
- /**
2
- * WU-HTML-PARSER: Fetch and parse HTML entries from micro-apps.
3
- *
4
- * Used in "strict" sandbox mode. The flow:
5
- * 1. Fetch the HTML page at the app's URL
6
- * 2. Parse it: extract inline/external scripts, inline/external styles, and clean DOM
7
- * 3. Return structured result so wu-core can inject DOM + styles into Shadow DOM
8
- * and execute scripts inside the proxy sandbox via WuScriptExecutor.
9
- *
10
- * This is the qiankun-style "HTML entry" approach that enables real JS isolation.
11
- */
12
-
13
- import { logger } from './wu-logger.js';
14
-
15
- export class WuHtmlParser {
16
- constructor() {
17
- this._cache = new Map();
18
- }
19
-
20
- /**
21
- * Fetch HTML content from a URL.
22
- * @param {string} url - App URL (e.g. http://localhost:3001)
23
- * @param {string} appName - For logging
24
- * @returns {Promise<string>} Raw HTML string
25
- */
26
- async fetchHtml(url, appName) {
27
- logger.wuDebug(`[HtmlParser] Fetching HTML for ${appName} from ${url}`);
28
-
29
- const response = await fetch(url, {
30
- method: 'GET',
31
- headers: { 'Accept': 'text/html,application/xhtml+xml,*/*' }
32
- });
33
-
34
- if (!response.ok) {
35
- throw new Error(`[HtmlParser] Failed to fetch ${url}: HTTP ${response.status}`);
36
- }
37
-
38
- const html = await response.text();
39
- if (!html || !html.trim()) {
40
- throw new Error(`[HtmlParser] Empty HTML response from ${url}`);
41
- }
42
-
43
- logger.wuDebug(`[HtmlParser] Fetched ${html.length} chars for ${appName}`);
44
- return html;
45
- }
46
-
47
- /**
48
- * Parse HTML string into structured parts.
49
- *
50
- * @param {string} html - Raw HTML
51
- * @param {string} appName - App identifier
52
- * @param {string} baseUrl - Base URL for resolving relative paths
53
- * @returns {{
54
- * dom: string,
55
- * scripts: { inline: string[], external: string[] },
56
- * styles: { inline: string[], external: string[] }
57
- * }}
58
- */
59
- parse(html, appName, baseUrl) {
60
- const cacheKey = `${appName}:${html.length}`;
61
- if (this._cache.has(cacheKey)) {
62
- return this._cache.get(cacheKey);
63
- }
64
-
65
- const temp = document.createElement('div');
66
- temp.innerHTML = html;
67
-
68
- const inlineScripts = [];
69
- const externalScripts = [];
70
- const inlineStyles = [];
71
- const externalStyles = [];
72
-
73
- this._extractResources(temp, {
74
- inlineScripts, externalScripts,
75
- inlineStyles, externalStyles,
76
- baseUrl
77
- });
78
-
79
- const result = {
80
- dom: temp.innerHTML,
81
- scripts: { inline: inlineScripts, external: externalScripts },
82
- styles: { inline: inlineStyles, external: externalStyles }
83
- };
84
-
85
- this._cache.set(cacheKey, result);
86
-
87
- logger.wuDebug(
88
- `[HtmlParser] ${appName}: ${inlineScripts.length} inline scripts, ` +
89
- `${externalScripts.length} external scripts, ` +
90
- `${inlineStyles.length + externalStyles.length} styles`
91
- );
92
-
93
- return result;
94
- }
95
-
96
- /**
97
- * Convenience: fetch + parse in one call.
98
- */
99
- async fetchAndParse(url, appName) {
100
- const html = await this.fetchHtml(url, appName);
101
- return this.parse(html, appName, url);
102
- }
103
-
104
- /**
105
- * Recursively walk the DOM, extracting scripts and styles,
106
- * replacing them with comments to keep the DOM clean.
107
- */
108
- _extractResources(element, ctx) {
109
- // Iterate over a static copy since we mutate the DOM
110
- const children = Array.from(element.children);
111
-
112
- for (const child of children) {
113
- const tag = child.nodeName.toLowerCase();
114
-
115
- if (tag === 'script') {
116
- this._extractScript(child, ctx);
117
- child.replaceWith(document.createComment('wu:script'));
118
- continue;
119
- }
120
-
121
- if (tag === 'style') {
122
- const text = child.textContent?.trim();
123
- if (text) ctx.inlineStyles.push(text);
124
- child.replaceWith(document.createComment('wu:style'));
125
- continue;
126
- }
127
-
128
- if (tag === 'link') {
129
- const rel = child.getAttribute('rel');
130
- const href = child.getAttribute('href');
131
- if (rel === 'stylesheet' && href) {
132
- ctx.externalStyles.push(this._resolveUrl(href, ctx.baseUrl));
133
- child.replaceWith(document.createComment('wu:link'));
134
- continue;
135
- }
136
- }
137
-
138
- // Recurse into children
139
- if (child.children.length > 0) {
140
- this._extractResources(child, ctx);
141
- }
142
- }
143
- }
144
-
145
- /**
146
- * Extract a <script> tag into inline or external list.
147
- * Skips type="module" scripts (they can't be eval'd — use module mode for those).
148
- */
149
- _extractScript(el, ctx) {
150
- const type = el.getAttribute('type') || '';
151
- const src = el.getAttribute('src');
152
-
153
- // Module scripts can't be executed via new Function / eval.
154
- // If the app uses ES modules, it should use sandbox: 'module' mode.
155
- if (type === 'module') {
156
- logger.wuDebug('[HtmlParser] Skipping type="module" script (use sandbox: "module" for ES modules)');
157
- return;
158
- }
159
-
160
- if (src) {
161
- ctx.externalScripts.push(this._resolveUrl(src, ctx.baseUrl));
162
- } else {
163
- const text = el.textContent?.trim();
164
- if (text) ctx.inlineScripts.push(text);
165
- }
166
- }
167
-
168
- /**
169
- * Resolve a relative URL against a base URL.
170
- */
171
- _resolveUrl(url, baseUrl) {
172
- if (url.startsWith('http://') || url.startsWith('https://')) return url;
173
- if (url.startsWith('//')) return `https:${url}`;
174
-
175
- try {
176
- return new URL(url, baseUrl).href;
177
- } catch {
178
- // Fallback for environments without URL constructor
179
- const base = baseUrl.replace(/\/$/, '');
180
- return url.startsWith('/') ? base + url : `${base}/${url}`;
181
- }
182
- }
183
-
184
- /**
185
- * Clear the parse cache.
186
- */
187
- clearCache() {
188
- this._cache.clear();
189
- }
190
- }
1
+ /**
2
+ * WU-HTML-PARSER: Fetch and parse HTML entries from micro-apps.
3
+ *
4
+ * Used in "strict" sandbox mode. The flow:
5
+ * 1. Fetch the HTML page at the app's URL
6
+ * 2. Parse it: extract inline/external scripts, inline/external styles, and clean DOM
7
+ * 3. Return structured result so wu-core can inject DOM + styles into Shadow DOM
8
+ * and execute scripts inside the proxy sandbox via WuScriptExecutor.
9
+ *
10
+ * This is the qiankun-style "HTML entry" approach that enables real JS isolation.
11
+ */
12
+
13
+ import { logger } from './wu-logger.js';
14
+
15
+ export class WuHtmlParser {
16
+ constructor() {
17
+ this._cache = new Map();
18
+ }
19
+
20
+ /**
21
+ * Fetch HTML content from a URL.
22
+ * @param {string} url - App URL (e.g. http://localhost:3001)
23
+ * @param {string} appName - For logging
24
+ * @returns {Promise<string>} Raw HTML string
25
+ */
26
+ async fetchHtml(url, appName) {
27
+ logger.wuDebug(`[HtmlParser] Fetching HTML for ${appName} from ${url}`);
28
+
29
+ const response = await fetch(url, {
30
+ method: 'GET',
31
+ headers: { 'Accept': 'text/html,application/xhtml+xml,*/*' }
32
+ });
33
+
34
+ if (!response.ok) {
35
+ throw new Error(`[HtmlParser] Failed to fetch ${url}: HTTP ${response.status}`);
36
+ }
37
+
38
+ const html = await response.text();
39
+ if (!html || !html.trim()) {
40
+ throw new Error(`[HtmlParser] Empty HTML response from ${url}`);
41
+ }
42
+
43
+ logger.wuDebug(`[HtmlParser] Fetched ${html.length} chars for ${appName}`);
44
+ return html;
45
+ }
46
+
47
+ /**
48
+ * Parse HTML string into structured parts.
49
+ *
50
+ * @param {string} html - Raw HTML
51
+ * @param {string} appName - App identifier
52
+ * @param {string} baseUrl - Base URL for resolving relative paths
53
+ * @returns {{
54
+ * dom: string,
55
+ * scripts: { inline: string[], external: string[] },
56
+ * styles: { inline: string[], external: string[] }
57
+ * }}
58
+ */
59
+ parse(html, appName, baseUrl) {
60
+ const cacheKey = `${appName}:${html.length}`;
61
+ if (this._cache.has(cacheKey)) {
62
+ return this._cache.get(cacheKey);
63
+ }
64
+
65
+ const parser = new DOMParser();
66
+ const doc = parser.parseFromString(html, 'text/html');
67
+
68
+ const inlineScripts = [];
69
+ const externalScripts = [];
70
+ const inlineStyles = [];
71
+ const externalStyles = [];
72
+
73
+ const ctx = {
74
+ inlineScripts, externalScripts,
75
+ inlineStyles, externalStyles,
76
+ baseUrl
77
+ };
78
+
79
+ // DOMParser moves <style>, <link>, and some <script> tags to <head>.
80
+ // Extract resources from both head and body to capture everything.
81
+ if (doc.head) {
82
+ this._extractResources(doc.head, ctx);
83
+ }
84
+
85
+ const temp = doc.body || doc.documentElement;
86
+ this._extractResources(temp, ctx);
87
+
88
+ const result = {
89
+ dom: temp.innerHTML,
90
+ scripts: { inline: inlineScripts, external: externalScripts },
91
+ styles: { inline: inlineStyles, external: externalStyles }
92
+ };
93
+
94
+ this._cache.set(cacheKey, result);
95
+
96
+ logger.wuDebug(
97
+ `[HtmlParser] ${appName}: ${inlineScripts.length} inline scripts, ` +
98
+ `${externalScripts.length} external scripts, ` +
99
+ `${inlineStyles.length + externalStyles.length} styles`
100
+ );
101
+
102
+ return result;
103
+ }
104
+
105
+ /**
106
+ * Convenience: fetch + parse in one call.
107
+ */
108
+ async fetchAndParse(url, appName) {
109
+ const html = await this.fetchHtml(url, appName);
110
+ return this.parse(html, appName, url);
111
+ }
112
+
113
+ /**
114
+ * Recursively walk the DOM, extracting scripts and styles,
115
+ * replacing them with comments to keep the DOM clean.
116
+ */
117
+ _extractResources(element, ctx) {
118
+ // Iterate over a static copy since we mutate the DOM
119
+ const children = Array.from(element.children);
120
+
121
+ for (const child of children) {
122
+ const tag = child.nodeName.toLowerCase();
123
+
124
+ if (tag === 'script') {
125
+ this._extractScript(child, ctx);
126
+ child.replaceWith(document.createComment('wu:script'));
127
+ continue;
128
+ }
129
+
130
+ if (tag === 'style') {
131
+ const text = child.textContent?.trim();
132
+ if (text) ctx.inlineStyles.push(text);
133
+ child.replaceWith(document.createComment('wu:style'));
134
+ continue;
135
+ }
136
+
137
+ if (tag === 'link') {
138
+ const rel = child.getAttribute('rel');
139
+ const href = child.getAttribute('href');
140
+ if (rel === 'stylesheet' && href) {
141
+ ctx.externalStyles.push(this._resolveUrl(href, ctx.baseUrl));
142
+ child.replaceWith(document.createComment('wu:link'));
143
+ continue;
144
+ }
145
+ }
146
+
147
+ // Recurse into children
148
+ if (child.children.length > 0) {
149
+ this._extractResources(child, ctx);
150
+ }
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Extract a <script> tag into inline or external list.
156
+ * Skips type="module" scripts (they can't be eval'd — use module mode for those).
157
+ */
158
+ _extractScript(el, ctx) {
159
+ const type = el.getAttribute('type') || '';
160
+ const src = el.getAttribute('src');
161
+
162
+ // Module scripts can't be executed via new Function / eval.
163
+ // If the app uses ES modules, it should use sandbox: 'module' mode.
164
+ if (type === 'module') {
165
+ logger.wuDebug('[HtmlParser] Skipping type="module" script (use sandbox: "module" for ES modules)');
166
+ return;
167
+ }
168
+
169
+ if (src) {
170
+ ctx.externalScripts.push(this._resolveUrl(src, ctx.baseUrl));
171
+ } else {
172
+ const text = el.textContent?.trim();
173
+ if (text) ctx.inlineScripts.push(text);
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Resolve a relative URL against a base URL.
179
+ */
180
+ _resolveUrl(url, baseUrl) {
181
+ if (url.startsWith('http://') || url.startsWith('https://')) return url;
182
+ if (url.startsWith('//')) return `https:${url}`;
183
+
184
+ try {
185
+ return new URL(url, baseUrl).href;
186
+ } catch {
187
+ // Fallback for environments without URL constructor
188
+ const base = baseUrl.replace(/\/$/, '');
189
+ return url.startsWith('/') ? base + url : `${base}/${url}`;
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Clear the parse cache.
195
+ */
196
+ clearCache() {
197
+ this._cache.clear();
198
+ }
199
+ }