wu-framework 1.1.16 → 1.1.18

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 (51) hide show
  1. package/README.md +52 -20
  2. package/package.json +48 -3
  3. package/src/adapters/alpine/index.d.ts +60 -0
  4. package/src/adapters/alpine/index.js +231 -0
  5. package/src/adapters/alpine.d.ts +3 -0
  6. package/src/adapters/alpine.js +3 -0
  7. package/src/adapters/htmx/index.d.ts +60 -0
  8. package/src/adapters/htmx/index.js +242 -0
  9. package/src/adapters/htmx.d.ts +3 -0
  10. package/src/adapters/htmx.js +3 -0
  11. package/src/adapters/index.js +60 -3
  12. package/src/adapters/qwik/index.d.ts +52 -0
  13. package/src/adapters/qwik/index.js +214 -0
  14. package/src/adapters/qwik.d.ts +3 -0
  15. package/src/adapters/qwik.js +3 -0
  16. package/src/adapters/react/ai.js +135 -135
  17. package/src/adapters/react/index.d.ts +246 -246
  18. package/src/adapters/react/index.js +695 -695
  19. package/src/adapters/stencil/index.d.ts +54 -0
  20. package/src/adapters/stencil/index.js +228 -0
  21. package/src/adapters/stencil.d.ts +3 -0
  22. package/src/adapters/stencil.js +3 -0
  23. package/src/adapters/stimulus/index.d.ts +60 -0
  24. package/src/adapters/stimulus/index.js +255 -0
  25. package/src/adapters/stimulus.d.ts +3 -0
  26. package/src/adapters/stimulus.js +3 -0
  27. package/src/adapters/svelte/index.js +1 -1
  28. package/src/adapters/vanilla/index.js +1 -1
  29. package/src/adapters/vue/index.js +8 -0
  30. package/src/core/wu-cache.js +24 -3
  31. package/src/core/wu-core.js +15 -1
  32. package/src/core/wu-error-boundary.js +17 -3
  33. package/src/core/wu-event-bus.js +43 -1
  34. package/src/core/wu-html-parser.js +13 -4
  35. package/src/core/wu-loader.js +162 -50
  36. package/src/core/wu-logger.js +21 -13
  37. package/src/core/wu-manifest.js +23 -0
  38. package/src/core/wu-plugin.js +57 -4
  39. package/src/core/wu-proxy-sandbox.js +2 -1
  40. package/src/core/wu-script-executor.js +48 -0
  41. package/src/core/wu-store.js +13 -3
  42. package/src/index.d.ts +317 -0
  43. package/src/index.js +11 -1
  44. package/dist/wu-framework.cjs.js +0 -3
  45. package/dist/wu-framework.cjs.js.map +0 -1
  46. package/dist/wu-framework.dev.js +0 -15302
  47. package/dist/wu-framework.dev.js.map +0 -1
  48. package/dist/wu-framework.esm.js +0 -3
  49. package/dist/wu-framework.esm.js.map +0 -1
  50. package/dist/wu-framework.umd.js +0 -3
  51. package/dist/wu-framework.umd.js.map +0 -1
@@ -11,7 +11,7 @@ import { logger } from './wu-logger.js';
11
11
 
12
12
 
13
13
  export class WuPluginSystem {
14
- constructor(core) {
14
+ constructor(core, options = {}) {
15
15
  this._core = core; // Privado - no expuesto a plugins
16
16
  this.plugins = new Map();
17
17
  this.hooks = new Map();
@@ -35,7 +35,7 @@ export class WuPluginSystem {
35
35
  ];
36
36
 
37
37
  // 🔐 Timeout para hooks (evita que plugins bloqueen)
38
- this.hookTimeout = 5000; // 5 segundos
38
+ this.hookTimeout = options.hookTimeout || 5000; // Default: 5 segundos
39
39
 
40
40
  this.availableHooks.forEach(hook => {
41
41
  this.hooks.set(hook, []);
@@ -106,8 +106,61 @@ export class WuPluginSystem {
106
106
  logger.warn('[WuPlugin] ⚠️ Plugin has unsafe access to core!');
107
107
  }
108
108
 
109
- // Congelar API para evitar modificaciones
110
- return Object.freeze(api);
109
+ // Congelar API recursivamente para evitar modificaciones en cualquier nivel
110
+ return WuPluginSystem._deepFreeze(api);
111
+ }
112
+
113
+ /**
114
+ * Deep-freeze an object and all its nested plain objects and arrays.
115
+ * Functions, DOM nodes, and other non-plain types are left untouched
116
+ * so they remain callable / functional. A WeakSet guards against
117
+ * circular references.
118
+ *
119
+ * @param {*} obj - The value to deep-freeze
120
+ * @param {WeakSet} [seen] - Internal tracker for circular references
121
+ * @returns {*} The same object, now deeply frozen
122
+ */
123
+ static _deepFreeze(obj, seen) {
124
+ if (obj === null || obj === undefined) {
125
+ return obj;
126
+ }
127
+
128
+ // Only freeze plain objects and arrays.
129
+ // Functions must stay invocable; DOM nodes, class instances, etc.
130
+ // should not be tampered with.
131
+ const dominated = typeof obj === 'object';
132
+ if (!dominated) {
133
+ return obj;
134
+ }
135
+
136
+ const isPlainObject =
137
+ Object.getPrototypeOf(obj) === Object.prototype ||
138
+ Object.getPrototypeOf(obj) === null;
139
+ const isArray = Array.isArray(obj);
140
+
141
+ if (!isPlainObject && !isArray) {
142
+ return obj;
143
+ }
144
+
145
+ // Circular-reference guard
146
+ if (!seen) {
147
+ seen = new WeakSet();
148
+ }
149
+ if (seen.has(obj)) {
150
+ return obj;
151
+ }
152
+ seen.add(obj);
153
+
154
+ // Recurse into own enumerable properties
155
+ const keys = Object.keys(obj);
156
+ for (let i = 0; i < keys.length; i++) {
157
+ const value = obj[keys[i]];
158
+ if (value !== null && value !== undefined && typeof value === 'object') {
159
+ WuPluginSystem._deepFreeze(value, seen);
160
+ }
161
+ }
162
+
163
+ return Object.freeze(obj);
111
164
  }
112
165
 
113
166
  /**
@@ -13,8 +13,9 @@
13
13
  import { logger } from './wu-logger.js';
14
14
 
15
15
  export class WuProxySandbox {
16
- constructor(appName) {
16
+ constructor(appName, options = {}) {
17
17
  this.appName = appName;
18
+ this.options = options;
18
19
  this.proxy = null;
19
20
  this.fakeWindow = Object.create(null);
20
21
  this.active = false;
@@ -15,6 +15,52 @@ import { logger } from './wu-logger.js';
15
15
 
16
16
  export class WuScriptExecutor {
17
17
 
18
+ /**
19
+ * Dangerous patterns that indicate prototype pollution, sandbox escape,
20
+ * or direct access to sensitive APIs. Each entry is a regex paired with
21
+ * a human-readable label used in error messages.
22
+ *
23
+ * This is a tripwire, not a full parser. It catches the most common
24
+ * attack vectors without the overhead of AST analysis.
25
+ */
26
+ static DANGEROUS_PATTERNS = [
27
+ // Prototype pollution vectors
28
+ { pattern: /constructor\s*\[\s*['"`]constructor['"`]\s*\]/, label: 'constructor chain access (sandbox escape)' },
29
+ { pattern: /__proto__/, label: '__proto__ access (prototype pollution)' },
30
+
31
+ // Sandbox escape via proxy introspection
32
+ { pattern: /Object\s*\.\s*getPrototypeOf\s*\(\s*proxy\s*\)/, label: 'Object.getPrototypeOf(proxy) (sandbox escape)' },
33
+
34
+ // Dynamic code generation that bypasses the sandbox
35
+ { pattern: /Function\s*\(\s*['"`]/, label: 'Function() constructor (dynamic code generation)' },
36
+ { pattern: /\beval\s*\(/, label: 'eval() (dynamic code execution)' },
37
+
38
+ // Dynamic import escapes the sandbox entirely (runs in global scope)
39
+ { pattern: /\bimport\s*\(/, label: 'import() (dynamic import escapes sandbox)' },
40
+
41
+ // Direct cookie access (should go through proxy traps, not raw document)
42
+ { pattern: /document\s*\.\s*cookie/, label: 'document.cookie (direct cookie access)' },
43
+ ];
44
+
45
+ /**
46
+ * Validate script text against known dangerous patterns before execution.
47
+ * Throws if any pattern matches. This is intentionally lightweight --
48
+ * pattern detection only, not a full parse.
49
+ *
50
+ * @param {string} scriptText - The raw script to validate
51
+ * @param {string} appName - App identifier (for error context)
52
+ * @throws {Error} If a dangerous pattern is detected
53
+ */
54
+ _validateScript(scriptText, appName) {
55
+ for (const { pattern, label } of WuScriptExecutor.DANGEROUS_PATTERNS) {
56
+ if (pattern.test(scriptText)) {
57
+ const msg = `[ScriptExecutor] Blocked dangerous pattern in "${appName}": ${label}`;
58
+ logger.wuError(msg);
59
+ throw new Error(msg);
60
+ }
61
+ }
62
+ }
63
+
18
64
  /**
19
65
  * Execute a script string inside the proxy sandbox.
20
66
  *
@@ -31,6 +77,8 @@ export class WuScriptExecutor {
31
77
 
32
78
  if (!scriptText || !scriptText.trim()) return;
33
79
 
80
+ this._validateScript(scriptText, appName);
81
+
34
82
  const sourceComment = sourceUrl ? `\n//# sourceURL=wu-sandbox:///${appName}/${sourceUrl}\n` : '';
35
83
 
36
84
  let wrappedCode;
@@ -8,6 +8,15 @@
8
8
  * - API minimalista: get(), set(), on()
9
9
  */
10
10
 
11
+ /**
12
+ * @typedef {Object} WuStoreMetrics
13
+ * @property {number} reads - Total read operations
14
+ * @property {number} writes - Total write operations
15
+ * @property {number} notifications - Total notifications sent
16
+ * @property {number} bufferUtilization - Ring buffer utilization (0-1)
17
+ * @property {number} listenerCount - Active listener count
18
+ */
19
+
11
20
  export class WuStore {
12
21
  constructor(bufferSize = 256) {
13
22
  // Ring Buffer configuration
@@ -63,8 +72,9 @@ export class WuStore {
63
72
  set(path, value) {
64
73
  this.metrics.writes++;
65
74
 
66
- // Write to ring buffer (lock-free)
67
- const sequence = this.cursor++;
75
+ // Write to ring buffer (lock-free, wraps at buffer boundary)
76
+ const sequence = this.cursor;
77
+ this.cursor = (this.cursor + 1) % (this.bufferSize * this.bufferSize);
68
78
  const index = sequence & this.mask;
69
79
 
70
80
  // Reuse buffer slot (zero allocation)
@@ -151,7 +161,7 @@ export class WuStore {
151
161
  getMetrics() {
152
162
  return {
153
163
  ...this.metrics,
154
- bufferUtilization: (this.cursor % this.bufferSize) / this.bufferSize,
164
+ bufferUtilization: Math.min(1, this.cursor / this.bufferSize),
155
165
  listenerCount: this.listeners.size + this.patternListeners.size
156
166
  };
157
167
  }
package/src/index.d.ts ADDED
@@ -0,0 +1,317 @@
1
+ // Wu Framework - Type Declarations
2
+
3
+ // --- Core Types ---
4
+
5
+ export interface WuEvent {
6
+ name: string;
7
+ data: any;
8
+ timestamp: number;
9
+ appName: string;
10
+ meta: Record<string, any>;
11
+ verified: boolean;
12
+ }
13
+
14
+ export interface WuAppConfig {
15
+ name: string;
16
+ url: string;
17
+ container?: string;
18
+ keepAlive?: boolean;
19
+ sandbox?: 'module' | 'strict' | 'eval';
20
+ styleMode?: 'shared' | 'isolated' | 'fully-isolated';
21
+ }
22
+
23
+ export interface WuLifecycle {
24
+ mount: (container: HTMLElement) => void | Promise<void>;
25
+ unmount?: (container: HTMLElement) => void | Promise<void>;
26
+ }
27
+
28
+ export interface WuPlugin {
29
+ name: string;
30
+ permissions?: Array<'mount' | 'events' | 'store' | 'apps' | 'config' | 'unsafe'>;
31
+ install?: (api: WuSandboxedApi, options?: any) => void;
32
+ uninstall?: (api: WuSandboxedApi) => void;
33
+ beforeInit?: (context: any) => void | Promise<void>;
34
+ afterInit?: (context: any) => void | Promise<void>;
35
+ beforeMount?: (context: any) => void | boolean | Promise<void | boolean>;
36
+ afterMount?: (context: any) => void | Promise<void>;
37
+ beforeUnmount?: (context: any) => void | Promise<void>;
38
+ afterUnmount?: (context: any) => void | Promise<void>;
39
+ onError?: (context: any) => void | Promise<void>;
40
+ onDestroy?: (context: any) => void | Promise<void>;
41
+ }
42
+
43
+ export interface WuSandboxedApi {
44
+ version: string;
45
+ info: { name: string; description: string; features: string[] };
46
+ getAppInfo(appName: string): { name: string; state: string; timestamp: number } | null;
47
+ getMountedApps(): string[];
48
+ getStats(): Record<string, any>;
49
+ emit?(event: string, data: any): boolean;
50
+ on?(event: string, cb: (event: WuEvent) => void): () => void;
51
+ off?(event: string, cb: (event: WuEvent) => void): void;
52
+ getState?(path: string): any;
53
+ setState?(path: string, value: any): number;
54
+ mount?(appName: string, container: string): Promise<void>;
55
+ unmount?(appName: string): Promise<void>;
56
+ }
57
+
58
+ // --- Core Classes ---
59
+
60
+ export class WuCore {
61
+ apps: Map<string, any>;
62
+ mounted: Map<string, any>;
63
+ eventBus: WuEventBus;
64
+ store: WuStore;
65
+ pluginSystem: WuPluginSystem;
66
+ hooks: WuLifecycleHooks;
67
+ performance: WuPerformance;
68
+
69
+ init(config: { apps: WuAppConfig[]; sandbox?: string; overrides?: any }): Promise<void>;
70
+ mount(appName: string, containerSelector: string): Promise<void>;
71
+ unmount(appName: string, options?: { force?: boolean; defer?: boolean }): Promise<void>;
72
+ define(appName: string, lifecycle: WuLifecycle): void;
73
+ app(name: string, config: Partial<WuAppConfig>): WuApp;
74
+ hide(appName: string): Promise<void>;
75
+ show(appName: string): Promise<void>;
76
+ isHidden(appName: string): boolean;
77
+ destroy(): void;
78
+ getStats(): Record<string, any>;
79
+ }
80
+
81
+ export class WuEventBus {
82
+ constructor();
83
+ emit(eventName: string, data?: any, options?: { appName?: string; token?: string; meta?: any }): boolean;
84
+ on(eventName: string, callback: (event: WuEvent) => void): () => void;
85
+ once(eventName: string, callback: (event: WuEvent) => void): () => void;
86
+ off(eventName: string, callback: (event: WuEvent) => void): void;
87
+ registerApp(appName: string, options?: { permissions?: string[]; token?: string }): string;
88
+ unregisterApp(appName: string): void;
89
+ replay(eventNameOrPattern: string, callback: (event: WuEvent) => void): void;
90
+ enableStrictMode(): void;
91
+ disableStrictMode(): void;
92
+ removeAll(): void;
93
+ getStats(): Record<string, any>;
94
+ configure(config: Partial<Record<string, any>>): void;
95
+ }
96
+
97
+ export class WuStore {
98
+ constructor(bufferSize?: number);
99
+ get(path?: string): any;
100
+ set(path: string, value: any): number;
101
+ on(pattern: string, callback: (value: any, path?: string) => void): () => void;
102
+ batch(updates: Record<string, any>): number[];
103
+ clear(): void;
104
+ getMetrics(): { reads: number; writes: number; notifications: number; bufferUtilization: number; listenerCount: number };
105
+ getRecentEvents(count?: number): Array<{ path: string; value: any; timestamp: number }>;
106
+ }
107
+
108
+ export class WuLoader {
109
+ constructor(options?: { maxCacheSize?: number; cacheTTL?: number });
110
+ loadApp(appUrl: string, manifest?: any): Promise<string>;
111
+ loadComponent(appUrl: string, componentPath: string): Promise<any>;
112
+ preload(appConfigs: WuAppConfig[]): Promise<void>;
113
+ isAvailable(url: string): Promise<boolean>;
114
+ clearCache(pattern?: string): void;
115
+ getStats(): Record<string, any>;
116
+ }
117
+
118
+ export class WuSandbox {
119
+ create(appName: string, container: HTMLElement, options?: any): any;
120
+ }
121
+
122
+ export class WuManifest {
123
+ load(appUrl: string): Promise<any>;
124
+ validate(manifest: any): any;
125
+ create(name: string, config?: any): any;
126
+ clearCache(pattern?: string): void;
127
+ }
128
+
129
+ export class WuApp {
130
+ mount(): Promise<void>;
131
+ unmount(): Promise<void>;
132
+ }
133
+
134
+ export class WuCache {
135
+ constructor(options?: { maxSize?: number; maxItems?: number; defaultTTL?: number; persistent?: boolean; storage?: string });
136
+ get(key: string): any;
137
+ set(key: string, value: any, ttl?: number): boolean;
138
+ delete(key: string): void;
139
+ clear(): void;
140
+ getStats(): Record<string, any>;
141
+ }
142
+
143
+ export class WuPerformance {
144
+ startMeasure(name: string, appName?: string): void;
145
+ endMeasure(name: string, appName?: string): number;
146
+ generateReport(): Record<string, any>;
147
+ }
148
+
149
+ export class WuProxySandbox {
150
+ constructor(appName: string, options?: Record<string, any>);
151
+ activate(): any;
152
+ deactivate(): void;
153
+ patchWindow(): void;
154
+ unpatchWindow(): void;
155
+ setContainer(container: HTMLElement, shadowRoot: ShadowRoot): void;
156
+ getProxy(): any;
157
+ isActive(): boolean;
158
+ getStats(): Record<string, any>;
159
+ }
160
+
161
+ export class WuSnapshotSandbox {
162
+ constructor(appName: string);
163
+ activate(): void;
164
+ deactivate(): void;
165
+ }
166
+
167
+ export class WuHtmlParser {
168
+ parse(html: string, appName: string, baseUrl: string): { dom: string; scripts: { inline: string[]; external: string[] }; styles: { inline: string[]; external: string[] } };
169
+ fetchHtml(url: string, appName: string): Promise<string>;
170
+ fetchAndParse(url: string, appName: string): Promise<any>;
171
+ clearCache(): void;
172
+ }
173
+
174
+ export class WuScriptExecutor {
175
+ execute(scriptText: string, appName: string, proxy: any, options?: { strictGlobal?: boolean; sourceUrl?: string }): any;
176
+ fetchScript(url: string): Promise<string>;
177
+ executeAll(scripts: Array<{ content?: string; src?: string }>, appName: string, proxy: any, options?: any): Promise<void>;
178
+ }
179
+
180
+ export class WuIframeSandbox {
181
+ constructor();
182
+ }
183
+
184
+ export class WuPluginSystem {
185
+ constructor(core: WuCore, options?: { hookTimeout?: number });
186
+ use(plugin: WuPlugin | ((options?: any) => WuPlugin), options?: any): void;
187
+ uninstall(pluginName: string): void;
188
+ getPlugin(pluginName: string): WuPlugin | undefined;
189
+ getStats(): Record<string, any>;
190
+ cleanup(): void;
191
+ }
192
+
193
+ export class WuLoadingStrategy {
194
+ constructor(core: WuCore);
195
+ }
196
+
197
+ export class WuPrefetch {
198
+ constructor(core: WuCore);
199
+ prefetch(appNames: string | string[], options?: any): Promise<void>;
200
+ prefetchAll(options?: any): Promise<void>;
201
+ }
202
+
203
+ export class WuOverrides {
204
+ constructor();
205
+ set(name: string, url: string, options?: any): void;
206
+ remove(name: string): void;
207
+ getAll(): Record<string, string>;
208
+ clearAll(): void;
209
+ }
210
+
211
+ export class WuErrorBoundary {
212
+ constructor(core: WuCore);
213
+ handle(error: Error, context?: any): Promise<{ recovered: boolean; action: string; message?: string }>;
214
+ register(handler: { name: string; canHandle: (error: Error) => boolean; handle: (error: Error, context: any) => Promise<any> }): void;
215
+ getErrorLog(limit?: number): any[];
216
+ getStats(): Record<string, any>;
217
+ }
218
+
219
+ export class WuLifecycleHooks {
220
+ constructor(core: WuCore);
221
+ use(phase: string, middleware: Function, options?: any): void;
222
+ execute(phase: string, context?: any): Promise<{ cancelled: boolean }>;
223
+ }
224
+
225
+ export class WuStyleBridge {}
226
+
227
+ // --- Hook Factories ---
228
+
229
+ export function createSimpleHook(fn: Function): any;
230
+ export function createConditionalHook(condition: Function, fn: Function): any;
231
+ export function createGuardHook(fn: Function): any;
232
+ export function createTransformHook(fn: Function): any;
233
+ export function createTimedHook(fn: Function, timeout: number): any;
234
+ export function createPlugin(config: WuPlugin): WuPlugin;
235
+
236
+ // --- Convenience API ---
237
+
238
+ export const wu: WuCore;
239
+ export default wu;
240
+
241
+ export function init(apps: WuAppConfig[]): Promise<void>;
242
+ export function mount(name: string, container: string): Promise<void>;
243
+ export function unmount(name: string, opts?: any): Promise<void>;
244
+ export function define(name: string, lifecycle: WuLifecycle): void;
245
+ export function app(name: string, config: Partial<WuAppConfig>): WuApp;
246
+ export function destroy(): void;
247
+ export function hide(name: string): Promise<void>;
248
+ export function show(name: string): Promise<void>;
249
+ export function isHidden(name: string): boolean;
250
+
251
+ export function emit(event: string, data?: any, opts?: any): boolean;
252
+ export function on(event: string, cb: (event: WuEvent) => void): () => void;
253
+ export function once(event: string, cb: (event: WuEvent) => void): () => void;
254
+ export function off(event: string, cb: (event: WuEvent) => void): void;
255
+
256
+ export function getState(path?: string): any;
257
+ export function setState(path: string, value: any): number;
258
+ export function onStateChange(pattern: string, cb: (value: any) => void): () => void;
259
+
260
+ export function startMeasure(name: string, app?: string): void;
261
+ export function endMeasure(name: string, app?: string): number;
262
+ export function generatePerformanceReport(): Record<string, any>;
263
+
264
+ export function prefetch(appNames: string | string[], opts?: any): Promise<void>;
265
+ export function prefetchAll(opts?: any): Promise<void>;
266
+
267
+ export function override(name: string, url: string, opts?: any): void;
268
+ export function removeOverride(name: string): void;
269
+ export function getOverrides(): Record<string, string>;
270
+ export function clearOverrides(): void;
271
+
272
+ export function usePlugin(plugin: WuPlugin | Function, opts?: any): void;
273
+ export function useHook(phase: string, middleware: Function, opts?: any): void;
274
+
275
+ export function silenceAllLogs(): void;
276
+ export function enableAllLogs(): void;
277
+
278
+ // --- AI Classes ---
279
+
280
+ export class WuAI {
281
+ provider(name: string, config: any): void;
282
+ send(message: string, options?: any): Promise<any>;
283
+ stream(message: string, options?: any): AsyncGenerator<any>;
284
+ json(message: string, options?: any): Promise<any>;
285
+ action(name: string, config: any): void;
286
+ agent(goal: string, options?: any): Promise<any>;
287
+ }
288
+
289
+ export class WuAIProvider {}
290
+ export class WuAIPermissions {}
291
+ export class WuAIContext {}
292
+ export class WuAIActions {}
293
+ export class WuAIConversation {}
294
+ export class WuAITriggers {}
295
+ export class WuAIAgent {}
296
+ export class WuAIOrchestrate {}
297
+
298
+ export function sanitizeForPrompt(text: string): string;
299
+ export function redactSensitive(text: string): string;
300
+ export function interpolate(template: string, vars: Record<string, any>): string;
301
+ export function buildToolSchemas(actions: any): any;
302
+ export function normalizeParameters(params: any): any;
303
+ export function validateParams(params: any, schema: any): boolean;
304
+ export function estimateTokens(text: string): number;
305
+ export function truncateToTokenBudget(text: string, budget: number): string;
306
+
307
+ // --- MCP & Browser ---
308
+
309
+ export function createMcpBridge(core: WuCore): any;
310
+ export function registerBrowserActions(ai: WuAI): void;
311
+ export function ensureInterceptors(): void;
312
+ export function captureScreenshot(): Promise<string>;
313
+ export function buildA11yTree(): any;
314
+ export function clickElement(selector: string): Promise<void>;
315
+ export function typeIntoElement(selector: string, text: string): Promise<void>;
316
+ export function getFilteredNetwork(): any[];
317
+ export function getFilteredConsole(): any[];
package/src/index.js CHANGED
@@ -25,14 +25,24 @@ if (typeof window !== 'undefined' && window.wu && window.wu._isWuFramework) {
25
25
  } else {
26
26
  wu = new WuCore();
27
27
  wu._isWuFramework = true;
28
+
29
+ // Also store on a Symbol key for collision-safe access
30
+ if (typeof window !== 'undefined') {
31
+ const WU_KEY = Symbol.for('wu-framework');
32
+ window[WU_KEY] = wu;
33
+ }
28
34
  }
29
35
 
30
36
  // Expose globally for microfrontends
31
37
  if (typeof window !== 'undefined') {
38
+ // Warn if window.wu exists but is not a Wu Framework instance
39
+ if (window.wu && !window.wu._isWuFramework) {
40
+ console.warn('[Wu Framework] window.wu already exists and is not a Wu Framework instance. Overwriting. Use Symbol.for("wu-framework") for collision-safe access.');
41
+ }
32
42
  window.wu = wu;
33
43
 
34
44
  if (!wu.version) {
35
- wu.version = '1.1.8';
45
+ wu.version = '1.1.17';
36
46
  wu.info = {
37
47
  name: 'Wu Framework',
38
48
  description: 'Universal Microfrontends',