wu-framework 1.1.6 → 1.1.8

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 (90) hide show
  1. package/README.md +511 -977
  2. package/dist/wu-framework.cjs.js +3 -1
  3. package/dist/wu-framework.cjs.js.map +1 -0
  4. package/dist/wu-framework.dev.js +7533 -2761
  5. package/dist/wu-framework.dev.js.map +1 -1
  6. package/dist/wu-framework.esm.js +3 -0
  7. package/dist/wu-framework.esm.js.map +1 -0
  8. package/dist/wu-framework.umd.js +3 -1
  9. package/dist/wu-framework.umd.js.map +1 -0
  10. package/integrations/astro/README.md +127 -0
  11. package/integrations/astro/WuApp.astro +63 -0
  12. package/integrations/astro/WuShell.astro +39 -0
  13. package/integrations/astro/index.js +68 -0
  14. package/integrations/astro/package.json +38 -0
  15. package/integrations/astro/types.d.ts +53 -0
  16. package/package.json +94 -74
  17. package/src/adapters/angular/ai.js +30 -0
  18. package/src/adapters/angular/index.d.ts +154 -0
  19. package/src/adapters/angular/index.js +932 -0
  20. package/src/adapters/angular.d.ts +3 -154
  21. package/src/adapters/angular.js +3 -813
  22. package/src/adapters/index.js +35 -24
  23. package/src/adapters/lit/ai.js +20 -0
  24. package/src/adapters/lit/index.d.ts +120 -0
  25. package/src/adapters/lit/index.js +721 -0
  26. package/src/adapters/lit.d.ts +3 -120
  27. package/src/adapters/lit.js +3 -726
  28. package/src/adapters/preact/ai.js +33 -0
  29. package/src/adapters/preact/index.d.ts +108 -0
  30. package/src/adapters/preact/index.js +661 -0
  31. package/src/adapters/preact.d.ts +3 -108
  32. package/src/adapters/preact.js +3 -665
  33. package/src/adapters/react/ai.js +135 -0
  34. package/src/adapters/react/index.d.ts +246 -0
  35. package/src/adapters/react/index.js +689 -0
  36. package/src/adapters/react.d.ts +3 -212
  37. package/src/adapters/react.js +3 -513
  38. package/src/adapters/shared.js +64 -0
  39. package/src/adapters/solid/ai.js +32 -0
  40. package/src/adapters/solid/index.d.ts +101 -0
  41. package/src/adapters/solid/index.js +586 -0
  42. package/src/adapters/solid.d.ts +3 -101
  43. package/src/adapters/solid.js +3 -591
  44. package/src/adapters/svelte/ai.js +31 -0
  45. package/src/adapters/svelte/index.d.ts +166 -0
  46. package/src/adapters/svelte/index.js +798 -0
  47. package/src/adapters/svelte.d.ts +3 -166
  48. package/src/adapters/svelte.js +3 -803
  49. package/src/adapters/vanilla/ai.js +30 -0
  50. package/src/adapters/vanilla/index.d.ts +179 -0
  51. package/src/adapters/vanilla/index.js +785 -0
  52. package/src/adapters/vanilla.d.ts +3 -179
  53. package/src/adapters/vanilla.js +3 -791
  54. package/src/adapters/vue/ai.js +52 -0
  55. package/src/adapters/vue/index.d.ts +299 -0
  56. package/src/adapters/vue/index.js +608 -0
  57. package/src/adapters/vue.d.ts +3 -299
  58. package/src/adapters/vue.js +3 -611
  59. package/src/ai/wu-ai-actions.js +261 -0
  60. package/src/ai/wu-ai-browser.js +663 -0
  61. package/src/ai/wu-ai-context.js +332 -0
  62. package/src/ai/wu-ai-conversation.js +554 -0
  63. package/src/ai/wu-ai-permissions.js +381 -0
  64. package/src/ai/wu-ai-provider.js +605 -0
  65. package/src/ai/wu-ai-schema.js +225 -0
  66. package/src/ai/wu-ai-triggers.js +396 -0
  67. package/src/ai/wu-ai.js +474 -0
  68. package/src/core/wu-app.js +50 -8
  69. package/src/core/wu-cache.js +1 -1
  70. package/src/core/wu-core.js +645 -677
  71. package/src/core/wu-html-parser.js +121 -211
  72. package/src/core/wu-iframe-sandbox.js +328 -0
  73. package/src/core/wu-mcp-bridge.js +647 -0
  74. package/src/core/wu-overrides.js +510 -0
  75. package/src/core/wu-prefetch.js +414 -0
  76. package/src/core/wu-proxy-sandbox.js +398 -75
  77. package/src/core/wu-sandbox.js +86 -268
  78. package/src/core/wu-script-executor.js +79 -182
  79. package/src/core/wu-snapshot-sandbox.js +149 -106
  80. package/src/core/wu-strategies.js +13 -0
  81. package/src/core/wu-style-bridge.js +0 -2
  82. package/src/index.js +139 -665
  83. package/dist/wu-framework.hex.js +0 -23
  84. package/dist/wu-framework.min.js +0 -1
  85. package/dist/wu-framework.obf.js +0 -1
  86. package/scripts/build-protected.js +0 -366
  87. package/scripts/build.js +0 -212
  88. package/scripts/rollup-plugin-hex.js +0 -143
  89. package/src/core/wu-registry.js +0 -60
  90. package/src/core/wu-sandbox-pool.js +0 -390
@@ -1,280 +1,190 @@
1
1
  /**
2
- * 📄 WU-HTML-PARSER: Parser inteligente de HTML para micro-apps
3
- * Basado en video-code - Extrae DOM, scripts y estilos
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.
4
11
  */
5
12
 
13
+ import { logger } from './wu-logger.js';
14
+
6
15
  export class WuHtmlParser {
7
16
  constructor() {
8
- this.cache = new Map(); // Cache de HTML parseado
9
- console.log('[WuHtmlParser] 📄 HTML parsing system initialized');
17
+ this._cache = new Map();
10
18
  }
11
19
 
12
20
  /**
13
- * Parsear HTML completo de una micro-app
14
- * @param {string} html - HTML a parsear
15
- * @param {string} appName - Nombre de la app
16
- * @param {string} baseUrl - URL base para resolver recursos
17
- * @returns {Object} { dom, scripts, styles, externalScripts, externalStyles }
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
18
25
  */
19
- parse(html, appName, baseUrl) {
20
- console.log(`[WuHtmlParser] 📄 Parsing HTML for ${appName}`);
26
+ async fetchHtml(url, appName) {
27
+ logger.wuDebug(`[HtmlParser] Fetching HTML for ${appName} from ${url}`);
21
28
 
22
- // Verificar cache
23
- const cacheKey = `${appName}:${html.length}`;
24
- if (this.cache.has(cacheKey)) {
25
- console.log(`[WuHtmlParser] ⚡ Cache hit for ${appName}`);
26
- return this.cache.get(cacheKey);
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}`);
27
36
  }
28
37
 
29
- try {
30
- // Crear contenedor temporal para parsear
31
- const tempDiv = document.createElement('div');
32
- tempDiv.innerHTML = html;
38
+ const html = await response.text();
39
+ if (!html || !html.trim()) {
40
+ throw new Error(`[HtmlParser] Empty HTML response from ${url}`);
41
+ }
33
42
 
34
- // Extraer recursos
35
- const inlineScripts = [];
36
- const externalScripts = [];
37
- const inlineStyles = [];
38
- const externalStyles = [];
43
+ logger.wuDebug(`[HtmlParser] Fetched ${html.length} chars for ${appName}`);
44
+ return html;
45
+ }
39
46
 
40
- // 🔍 Parsear recursivamente el DOM
41
- this.deepParse(tempDiv, {
42
- inlineScripts,
43
- externalScripts,
44
- inlineStyles,
45
- externalStyles,
46
- baseUrl,
47
- appName
48
- });
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
+ }
49
64
 
50
- // Obtener DOM limpio
51
- const cleanedDom = tempDiv.innerHTML;
65
+ const temp = document.createElement('div');
66
+ temp.innerHTML = html;
52
67
 
53
- const result = {
54
- dom: cleanedDom,
55
- scripts: {
56
- inline: inlineScripts,
57
- external: externalScripts,
58
- all: [...inlineScripts, ...externalScripts]
59
- },
60
- styles: {
61
- inline: inlineStyles,
62
- external: externalStyles,
63
- all: [...inlineStyles, ...externalStyles]
64
- }
65
- };
68
+ const inlineScripts = [];
69
+ const externalScripts = [];
70
+ const inlineStyles = [];
71
+ const externalStyles = [];
66
72
 
67
- // Cachear resultado
68
- this.cache.set(cacheKey, result);
73
+ this._extractResources(temp, {
74
+ inlineScripts, externalScripts,
75
+ inlineStyles, externalStyles,
76
+ baseUrl
77
+ });
69
78
 
70
- console.log(`[WuHtmlParser] Parsed ${appName}: ${inlineScripts.length} inline scripts, ${externalScripts.length} external scripts`);
79
+ const result = {
80
+ dom: temp.innerHTML,
81
+ scripts: { inline: inlineScripts, external: externalScripts },
82
+ styles: { inline: inlineStyles, external: externalStyles }
83
+ };
71
84
 
72
- return result;
85
+ this._cache.set(cacheKey, result);
73
86
 
74
- } catch (error) {
75
- console.error(`[WuHtmlParser] Failed to parse HTML for ${appName}:`, error);
76
- throw error;
77
- }
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;
78
94
  }
79
95
 
80
96
  /**
81
- * Parsear recursivamente el DOM extrayendo scripts y estilos
82
- * @param {HTMLElement} element - Elemento a parsear
83
- * @param {Object} context - Contexto de parsing
97
+ * Convenience: fetch + parse in one call.
84
98
  */
85
- deepParse(element, context) {
86
- const { inlineScripts, externalScripts, inlineStyles, externalStyles, baseUrl, appName } = context;
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
87
110
  const children = Array.from(element.children);
88
111
 
89
112
  for (const child of children) {
90
- const tagName = child.nodeName.toLowerCase();
91
-
92
- // 📜 SCRIPT TAGS
93
- if (tagName === 'script') {
94
- this.parseScriptTag(child, inlineScripts, externalScripts, baseUrl, appName);
113
+ const tag = child.nodeName.toLowerCase();
95
114
 
96
- // Reemplazar script con comentario
97
- const comment = document.createComment(`Wu: script removed from ${appName}`);
98
- child.parentElement?.replaceChild(comment, child);
115
+ if (tag === 'script') {
116
+ this._extractScript(child, ctx);
117
+ child.replaceWith(document.createComment('wu:script'));
99
118
  continue;
100
119
  }
101
120
 
102
- // 🎨 STYLE TAGS
103
- if (tagName === 'style') {
104
- const styleContent = child.textContent || '';
105
- if (styleContent.trim()) {
106
- inlineStyles.push(styleContent);
107
- console.log(`[WuHtmlParser] 🎨 Extracted inline style (${styleContent.length} chars)`);
108
- }
109
-
110
- // Reemplazar style con comentario
111
- const comment = document.createComment(`Wu: style removed from ${appName}`);
112
- child.parentElement?.replaceChild(comment, child);
121
+ if (tag === 'style') {
122
+ const text = child.textContent?.trim();
123
+ if (text) ctx.inlineStyles.push(text);
124
+ child.replaceWith(document.createComment('wu:style'));
113
125
  continue;
114
126
  }
115
127
 
116
- // 🔗 LINK TAGS (external styles)
117
- if (tagName === 'link') {
128
+ if (tag === 'link') {
118
129
  const rel = child.getAttribute('rel');
119
130
  const href = child.getAttribute('href');
120
-
121
131
  if (rel === 'stylesheet' && href) {
122
- const absoluteUrl = this.resolveUrl(href, baseUrl);
123
- externalStyles.push(absoluteUrl);
124
- console.log(`[WuHtmlParser] 🔗 Extracted external style: ${absoluteUrl}`);
125
-
126
- // Reemplazar link con comentario
127
- const comment = document.createComment(`Wu: link removed from ${appName}`);
128
- child.parentElement?.replaceChild(comment, child);
132
+ ctx.externalStyles.push(this._resolveUrl(href, ctx.baseUrl));
133
+ child.replaceWith(document.createComment('wu:link'));
129
134
  continue;
130
135
  }
131
136
  }
132
137
 
133
- // Recursión para elementos hijos
138
+ // Recurse into children
134
139
  if (child.children.length > 0) {
135
- this.deepParse(child, context);
140
+ this._extractResources(child, ctx);
136
141
  }
137
142
  }
138
143
  }
139
144
 
140
145
  /**
141
- * Parsear tag <script>
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).
142
148
  */
143
- parseScriptTag(scriptElement, inlineScripts, externalScripts, baseUrl, appName) {
144
- const src = scriptElement.getAttribute('src');
145
- const type = scriptElement.getAttribute('type') || 'text/javascript';
149
+ _extractScript(el, ctx) {
150
+ const type = el.getAttribute('type') || '';
151
+ const src = el.getAttribute('src');
146
152
 
147
- // Ignorar module scripts (se cargan por import)
153
+ // Module scripts can't be executed via new Function / eval.
154
+ // If the app uses ES modules, it should use sandbox: 'module' mode.
148
155
  if (type === 'module') {
149
- console.log(`[WuHtmlParser] ⏭️ Skipping module script for ${appName}`);
156
+ logger.wuDebug('[HtmlParser] Skipping type="module" script (use sandbox: "module" for ES modules)');
150
157
  return;
151
158
  }
152
159
 
153
160
  if (src) {
154
- // Script externo
155
- const absoluteUrl = this.resolveUrl(src, baseUrl);
156
- externalScripts.push(absoluteUrl);
157
- console.log(`[WuHtmlParser] 📜 Extracted external script: ${absoluteUrl}`);
158
- } else {
159
- // Script inline
160
- const scriptContent = scriptElement.textContent || '';
161
- if (scriptContent.trim()) {
162
- inlineScripts.push(scriptContent);
163
- console.log(`[WuHtmlParser] 📜 Extracted inline script (${scriptContent.length} chars)`);
164
- }
165
- }
166
- }
167
-
168
- /**
169
- * Resolver URL relativa a absoluta
170
- */
171
- resolveUrl(url, baseUrl) {
172
- // Ya es absoluta
173
- if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('//')) {
174
- return url.startsWith('//') ? `https:${url}` : url;
175
- }
176
-
177
- // Resolver relativa
178
- const base = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
179
-
180
- if (url.startsWith('/')) {
181
- // Relativa a raíz
182
- const urlObj = new URL(baseUrl);
183
- return `${urlObj.protocol}//${urlObj.host}${url}`;
161
+ ctx.externalScripts.push(this._resolveUrl(src, ctx.baseUrl));
184
162
  } else {
185
- // Relativa a base
186
- return `${base}${url}`;
163
+ const text = el.textContent?.trim();
164
+ if (text) ctx.inlineScripts.push(text);
187
165
  }
188
166
  }
189
167
 
190
168
  /**
191
- * Cargar HTML desde URL
169
+ * Resolve a relative URL against a base URL.
192
170
  */
193
- async fetchHtml(url, appName) {
194
- console.log(`[WuHtmlParser] 🌐 Fetching HTML for ${appName} from ${url}`);
171
+ _resolveUrl(url, baseUrl) {
172
+ if (url.startsWith('http://') || url.startsWith('https://')) return url;
173
+ if (url.startsWith('//')) return `https:${url}`;
195
174
 
196
175
  try {
197
- const response = await fetch(url, {
198
- method: 'GET',
199
- cache: 'no-cache',
200
- headers: {
201
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
202
- }
203
- });
204
-
205
- if (!response.ok) {
206
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
207
- }
208
-
209
- const html = await response.text();
210
-
211
- if (!html || html.trim().length === 0) {
212
- throw new Error('Empty HTML response');
213
- }
214
-
215
- console.log(`[WuHtmlParser] ✅ Fetched HTML (${html.length} chars)`);
216
-
217
- return html;
218
-
219
- } catch (error) {
220
- console.error(`[WuHtmlParser] ❌ Failed to fetch HTML from ${url}:`, error);
221
- throw error;
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}`;
222
181
  }
223
182
  }
224
183
 
225
184
  /**
226
- * Parsear y cargar HTML desde URL
185
+ * Clear the parse cache.
227
186
  */
228
- async parseFromUrl(url, appName) {
229
- const html = await this.fetchHtml(url, appName);
230
- return this.parse(html, appName, url);
187
+ clearCache() {
188
+ this._cache.clear();
231
189
  }
232
-
233
- /**
234
- * Limpiar cache
235
- */
236
- clearCache(pattern) {
237
- if (pattern) {
238
- const regex = new RegExp(pattern);
239
- for (const [key] of this.cache) {
240
- if (regex.test(key)) {
241
- this.cache.delete(key);
242
- console.log(`[WuHtmlParser] 🗑️ Cleared cache for: ${key}`);
243
- }
244
- }
245
- } else {
246
- this.cache.clear();
247
- console.log(`[WuHtmlParser] 🗑️ Cache cleared completely`);
248
- }
249
- }
250
-
251
- /**
252
- * Obtener estadísticas
253
- */
254
- getStats() {
255
- return {
256
- cacheSize: this.cache.size,
257
- cacheKeys: Array.from(this.cache.keys())
258
- };
259
- }
260
- }
261
-
262
- /**
263
- * 🎯 EXPORTS DE CONVENIENCIA
264
- */
265
-
266
- /**
267
- * Parsear HTML
268
- */
269
- export function parseHtml(html, appName, baseUrl) {
270
- const parser = new WuHtmlParser();
271
- return parser.parse(html, appName, baseUrl);
272
- }
273
-
274
- /**
275
- * Parsear HTML desde URL
276
- */
277
- export async function parseHtmlFromUrl(url, appName) {
278
- const parser = new WuHtmlParser();
279
- return await parser.parseFromUrl(url, appName);
280
190
  }