wu-framework 1.2.1 → 2.1.1

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 (164) hide show
  1. package/LICENSE +39 -39
  2. package/README.md +570 -489
  3. package/dist/adapters/alpine/index.js +2 -0
  4. package/dist/adapters/alpine/index.js.map +1 -0
  5. package/{src → dist}/adapters/angular/index.d.ts +154 -154
  6. package/dist/adapters/angular/index.js +2 -0
  7. package/dist/adapters/angular/index.js.map +1 -0
  8. package/{src → dist}/adapters/angular.d.ts +3 -3
  9. package/dist/adapters/htmx/index.js +2 -0
  10. package/dist/adapters/htmx/index.js.map +1 -0
  11. package/dist/adapters/index.js +2 -0
  12. package/dist/adapters/index.js.map +1 -0
  13. package/{src → dist}/adapters/lit/index.d.ts +120 -120
  14. package/dist/adapters/lit/index.js +44 -0
  15. package/dist/adapters/lit/index.js.map +1 -0
  16. package/{src → dist}/adapters/lit.d.ts +3 -3
  17. package/{src → dist}/adapters/preact/index.d.ts +108 -108
  18. package/dist/adapters/preact/index.js +2 -0
  19. package/dist/adapters/preact/index.js.map +1 -0
  20. package/{src → dist}/adapters/preact.d.ts +3 -3
  21. package/dist/adapters/qwik/index.js +2 -0
  22. package/dist/adapters/qwik/index.js.map +1 -0
  23. package/{src → dist}/adapters/react/index.d.ts +246 -246
  24. package/dist/adapters/react/index.js +2 -0
  25. package/dist/adapters/react/index.js.map +1 -0
  26. package/{src → dist}/adapters/react.d.ts +3 -3
  27. package/dist/adapters/shared.js +2 -0
  28. package/dist/adapters/shared.js.map +1 -0
  29. package/{src → dist}/adapters/solid/index.d.ts +101 -101
  30. package/dist/adapters/solid/index.js +2 -0
  31. package/dist/adapters/solid/index.js.map +1 -0
  32. package/{src → dist}/adapters/solid.d.ts +3 -3
  33. package/dist/adapters/stencil/index.js +2 -0
  34. package/dist/adapters/stencil/index.js.map +1 -0
  35. package/dist/adapters/stimulus/index.js +2 -0
  36. package/dist/adapters/stimulus/index.js.map +1 -0
  37. package/{src → dist}/adapters/svelte/index.d.ts +166 -166
  38. package/dist/adapters/svelte/index.js +2 -0
  39. package/dist/adapters/svelte/index.js.map +1 -0
  40. package/{src → dist}/adapters/svelte.d.ts +3 -3
  41. package/{src → dist}/adapters/vanilla/index.d.ts +179 -179
  42. package/dist/adapters/vanilla/index.js +2 -0
  43. package/dist/adapters/vanilla/index.js.map +1 -0
  44. package/{src → dist}/adapters/vanilla.d.ts +3 -3
  45. package/{src → dist}/adapters/vue/index.d.ts +299 -299
  46. package/dist/adapters/vue/index.js +2 -0
  47. package/dist/adapters/vue/index.js.map +1 -0
  48. package/{src → dist}/adapters/vue.d.ts +3 -3
  49. package/dist/ai/wu-ai.js +2 -0
  50. package/dist/ai/wu-ai.js.map +1 -0
  51. package/dist/core/wu-html-parser.js +2 -0
  52. package/dist/core/wu-html-parser.js.map +1 -0
  53. package/dist/core/wu-iframe-sandbox.js +2 -0
  54. package/dist/core/wu-iframe-sandbox.js.map +1 -0
  55. package/dist/core/wu-loader.js +2 -0
  56. package/dist/core/wu-loader.js.map +1 -0
  57. package/dist/core/wu-mcp-bridge.js +2 -0
  58. package/dist/core/wu-mcp-bridge.js.map +1 -0
  59. package/dist/core/wu-script-executor.js +2 -0
  60. package/dist/core/wu-script-executor.js.map +1 -0
  61. package/{src → dist}/index.d.ts +445 -317
  62. package/dist/wu-ai-browser-primitives-BDKXJlwc.js +2 -0
  63. package/dist/wu-ai-browser-primitives-BDKXJlwc.js.map +1 -0
  64. package/dist/wu-framework.cjs.js +2 -2
  65. package/dist/wu-framework.cjs.js.map +1 -1
  66. package/dist/wu-framework.dev.js +8681 -15683
  67. package/dist/wu-framework.dev.js.map +1 -1
  68. package/dist/wu-framework.esm.js +2 -2
  69. package/dist/wu-framework.esm.js.map +1 -1
  70. package/dist/wu-framework.umd.js +2 -2
  71. package/dist/wu-framework.umd.js.map +1 -1
  72. package/dist/wu-logger-fJfUHBGA.js +2 -0
  73. package/dist/wu-logger-fJfUHBGA.js.map +1 -0
  74. package/integrations/astro/README.md +127 -127
  75. package/integrations/astro/WuApp.astro +63 -63
  76. package/integrations/astro/WuShell.astro +39 -39
  77. package/integrations/astro/index.js +68 -68
  78. package/integrations/astro/package.json +38 -38
  79. package/integrations/astro/types.d.ts +53 -53
  80. package/package.json +218 -209
  81. package/src/adapters/alpine/index.js +0 -231
  82. package/src/adapters/alpine.js +0 -3
  83. package/src/adapters/angular/ai.js +0 -30
  84. package/src/adapters/angular/index.js +0 -932
  85. package/src/adapters/angular.js +0 -3
  86. package/src/adapters/htmx/index.js +0 -242
  87. package/src/adapters/htmx.js +0 -3
  88. package/src/adapters/index.js +0 -225
  89. package/src/adapters/lit/ai.js +0 -20
  90. package/src/adapters/lit/index.js +0 -721
  91. package/src/adapters/lit.js +0 -3
  92. package/src/adapters/preact/ai.js +0 -33
  93. package/src/adapters/preact/index.js +0 -661
  94. package/src/adapters/preact.js +0 -3
  95. package/src/adapters/qwik/index.js +0 -108
  96. package/src/adapters/qwik.js +0 -3
  97. package/src/adapters/react/ai.js +0 -135
  98. package/src/adapters/react/index.js +0 -695
  99. package/src/adapters/react.js +0 -3
  100. package/src/adapters/shared.js +0 -64
  101. package/src/adapters/solid/ai.js +0 -32
  102. package/src/adapters/solid/index.js +0 -586
  103. package/src/adapters/solid.js +0 -3
  104. package/src/adapters/stencil/index.js +0 -228
  105. package/src/adapters/stencil.js +0 -3
  106. package/src/adapters/stimulus/index.js +0 -255
  107. package/src/adapters/stimulus.js +0 -3
  108. package/src/adapters/svelte/ai.js +0 -31
  109. package/src/adapters/svelte/index.js +0 -798
  110. package/src/adapters/svelte.js +0 -3
  111. package/src/adapters/vanilla/ai.js +0 -30
  112. package/src/adapters/vanilla/index.js +0 -785
  113. package/src/adapters/vanilla.js +0 -3
  114. package/src/adapters/vue/ai.js +0 -52
  115. package/src/adapters/vue/index.js +0 -618
  116. package/src/adapters/vue.js +0 -3
  117. package/src/ai/wu-ai-actions.js +0 -261
  118. package/src/ai/wu-ai-agent.js +0 -546
  119. package/src/ai/wu-ai-browser-primitives.js +0 -354
  120. package/src/ai/wu-ai-browser.js +0 -380
  121. package/src/ai/wu-ai-context.js +0 -332
  122. package/src/ai/wu-ai-conversation.js +0 -613
  123. package/src/ai/wu-ai-orchestrate.js +0 -1021
  124. package/src/ai/wu-ai-permissions.js +0 -381
  125. package/src/ai/wu-ai-provider.js +0 -700
  126. package/src/ai/wu-ai-schema.js +0 -225
  127. package/src/ai/wu-ai-triggers.js +0 -396
  128. package/src/ai/wu-ai.js +0 -804
  129. package/src/core/wu-app.js +0 -236
  130. package/src/core/wu-cache.js +0 -498
  131. package/src/core/wu-core.js +0 -1412
  132. package/src/core/wu-error-boundary.js +0 -396
  133. package/src/core/wu-event-bus.js +0 -390
  134. package/src/core/wu-hooks.js +0 -350
  135. package/src/core/wu-html-parser.js +0 -199
  136. package/src/core/wu-iframe-sandbox.js +0 -328
  137. package/src/core/wu-loader.js +0 -450
  138. package/src/core/wu-logger.js +0 -143
  139. package/src/core/wu-manifest.js +0 -533
  140. package/src/core/wu-mcp-bridge.js +0 -432
  141. package/src/core/wu-overrides.js +0 -510
  142. package/src/core/wu-performance.js +0 -228
  143. package/src/core/wu-plugin.js +0 -401
  144. package/src/core/wu-prefetch.js +0 -414
  145. package/src/core/wu-proxy-sandbox.js +0 -477
  146. package/src/core/wu-sandbox.js +0 -779
  147. package/src/core/wu-script-executor.js +0 -161
  148. package/src/core/wu-sentinel-client.js +0 -311
  149. package/src/core/wu-snapshot-sandbox.js +0 -227
  150. package/src/core/wu-store.js +0 -307
  151. package/src/core/wu-strategies.js +0 -256
  152. package/src/core/wu-style-bridge.js +0 -477
  153. package/src/index.js +0 -234
  154. package/src/utils/dependency-resolver.js +0 -328
  155. /package/{src → dist}/adapters/alpine/index.d.ts +0 -0
  156. /package/{src → dist}/adapters/alpine.d.ts +0 -0
  157. /package/{src → dist}/adapters/htmx/index.d.ts +0 -0
  158. /package/{src → dist}/adapters/htmx.d.ts +0 -0
  159. /package/{src → dist}/adapters/qwik/index.d.ts +0 -0
  160. /package/{src → dist}/adapters/qwik.d.ts +0 -0
  161. /package/{src → dist}/adapters/stencil/index.d.ts +0 -0
  162. /package/{src → dist}/adapters/stencil.d.ts +0 -0
  163. /package/{src → dist}/adapters/stimulus/index.d.ts +0 -0
  164. /package/{src → dist}/adapters/stimulus.d.ts +0 -0
@@ -1,932 +0,0 @@
1
- /**
2
- * 🚀 WU-FRAMEWORK ANGULAR ADAPTER
3
- *
4
- * Integrates Angular (14+) with Wu Framework as microfrontends.
5
- * Supports NgModule-based apps, standalone components, and Angular Elements.
6
- * Works inside Shadow DOM (wu-framework's default isolation mode).
7
- *
8
- * ## Quick Start — Standalone Component (recommended)
9
- *
10
- * ```ts
11
- * // main.ts
12
- * import 'zone.js';
13
- * import '@angular/compiler'; // JIT mode (no AOT plugin needed)
14
- * import { createApplication } from '@angular/platform-browser';
15
- * import { createComponent, provideZoneChangeDetection } from '@angular/core';
16
- * import { wuAngular } from 'wu-framework/adapters/angular';
17
- * import { AppComponent } from './app/app.component';
18
- *
19
- * wuAngular.registerStandalone('my-app', AppComponent, {
20
- * createApplication, // pass Angular APIs to avoid bundler issues
21
- * createComponent,
22
- * provideZoneChangeDetection,
23
- * });
24
- * ```
25
- *
26
- * ## Using Wu Events & Store inside Angular
27
- *
28
- * ```ts
29
- * import { createWuService } from 'wu-framework/adapters/angular';
30
- *
31
- * @Component({ ... })
32
- * export class MyComponent implements OnInit, OnDestroy {
33
- * private wu = createWuService();
34
- *
35
- * ngOnInit() {
36
- * this.wu.on('some:event', (data) => { ... });
37
- * const user = this.wu.getState('user');
38
- * }
39
- *
40
- * ngOnDestroy() {
41
- * this.wu.destroy(); // cleans up all subscriptions
42
- * }
43
- * }
44
- * ```
45
- *
46
- * ## Vite Setup (no AnalogJS required)
47
- *
48
- * ```ts
49
- * // vite.config.ts
50
- * import { defineConfig } from 'vite';
51
- * export default defineConfig({
52
- * server: { port: 5008, cors: true },
53
- * esbuild: { target: 'es2022' },
54
- * });
55
- * ```
56
- *
57
- * ```json
58
- * // tsconfig.json — enable decorators for esbuild
59
- * { "compilerOptions": { "experimentalDecorators": true, "useDefineForClassFields": false } }
60
- * ```
61
- *
62
- * ## Why pass Angular APIs as options?
63
- *
64
- * When wu-framework is linked via `file:` or a monorepo, bundlers (Vite, Rollup)
65
- * resolve imports relative to the adapter's source file — NOT your app's node_modules.
66
- * Passing `createApplication`, `createComponent`, etc. from your own imports ensures
67
- * the bundler resolves them from your app's dependencies. The adapter falls back to
68
- * dynamic imports for environments where this isn't an issue (Webpack, non-bundled).
69
- */
70
-
71
- /**
72
- * Dynamic import helper — passes the module path through a function parameter
73
- * so that bundlers (Vite, Rollup, Webpack) cannot statically resolve it.
74
- * This is necessary because Angular dependencies (@angular/platform-browser-dynamic,
75
- * @angular/elements, etc.) are optional and may not be installed.
76
- */
77
- function _optionalImport(modulePath) {
78
- return import(/* @vite-ignore */ modulePath);
79
- }
80
-
81
- // Estado global del adapter
82
- const adapterState = {
83
- apps: new Map(),
84
- platformRef: null,
85
- initialized: false
86
- };
87
-
88
- /**
89
- * Obtiene la instancia de Wu Framework
90
- */
91
- function getWuInstance() {
92
- if (typeof window === 'undefined') return null;
93
-
94
- return window.wu
95
- || window.parent?.wu
96
- || window.top?.wu
97
- || null;
98
- }
99
-
100
- /**
101
- * Espera a que Wu Framework esté disponible
102
- */
103
- function waitForWu(timeout = 5000) {
104
- return new Promise((resolve, reject) => {
105
- const wu = getWuInstance();
106
- if (wu) {
107
- resolve(wu);
108
- return;
109
- }
110
-
111
- const startTime = Date.now();
112
-
113
- const handleWuReady = () => {
114
- cleanup();
115
- resolve(getWuInstance());
116
- };
117
-
118
- window.addEventListener('wu:ready', handleWuReady);
119
- window.addEventListener('wu:app:ready', handleWuReady);
120
-
121
- const checkInterval = setInterval(() => {
122
- const wu = getWuInstance();
123
- if (wu) {
124
- cleanup();
125
- resolve(wu);
126
- return;
127
- }
128
-
129
- if (Date.now() - startTime > timeout) {
130
- cleanup();
131
- reject(new Error(`Wu Framework not found after ${timeout}ms`));
132
- }
133
- }, 200);
134
-
135
- function cleanup() {
136
- clearInterval(checkInterval);
137
- window.removeEventListener('wu:ready', handleWuReady);
138
- window.removeEventListener('wu:app:ready', handleWuReady);
139
- }
140
- });
141
- }
142
-
143
- /**
144
- * Register an NgModule-based Angular app as a microfrontend.
145
- *
146
- * NOTE: Uses platformBrowserDynamic + bootstrapModule which does NOT work inside
147
- * Shadow DOM (it calls document.querySelector internally). For Shadow DOM compatibility,
148
- * use registerStandalone() instead — it uses createApplication + createComponent with
149
- * an explicit hostElement, which works everywhere.
150
- *
151
- * @param {string} appName - Unique name for the microfrontend
152
- * @param {Type<any>} AppModule - Main Angular module (e.g. AppModule)
153
- * @param {Object} options
154
- * @param {Function} options.platformFactory - platformBrowserDynamic (pass it to avoid bundler issues)
155
- * @param {Array} options.providers - Additional bootstrap providers
156
- * @param {Function} options.onMount - Called after mount
157
- * @param {Function} options.onUnmount - Called before unmount
158
- * @param {boolean} options.standalone - Allow standalone fallback (default: true)
159
- * @param {string} options.standaloneContainer - Selector for standalone mode (default: '#root')
160
- * @param {string} options.rootSelector - Root component selector (default: 'app-root')
161
- *
162
- * @example
163
- * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
164
- * import { wuAngular } from 'wu-framework/adapters/angular';
165
- * import { AppModule } from './app/app.module';
166
- *
167
- * wuAngular.register('my-app', AppModule, {
168
- * platformFactory: platformBrowserDynamic, // pass to avoid bundler issues
169
- * });
170
- */
171
- async function register(appName, AppModule, options = {}) {
172
- const {
173
- platformFactory = null,
174
- providers = [],
175
- onMount = null,
176
- onUnmount = null,
177
- standalone = true,
178
- standaloneContainer = '#root',
179
- rootSelector = 'app-root'
180
- } = options;
181
-
182
- // Función de mount interna
183
- const mountApp = async (container) => {
184
- if (!container) {
185
- console.error(`[WuAngular] Mount failed for ${appName}: container is null`);
186
- return;
187
- }
188
-
189
- // Evitar doble mount
190
- if (adapterState.apps.has(appName)) {
191
- console.warn(`[WuAngular] ${appName} already mounted, unmounting first`);
192
- await unmountApp();
193
- }
194
-
195
- try {
196
- // Crear elemento root para Angular
197
- const appElement = document.createElement(rootSelector);
198
- appElement.setAttribute('data-wu-angular-root', appName);
199
- container.innerHTML = '';
200
- container.appendChild(appElement);
201
-
202
- // Obtener platformBrowserDynamic
203
- let platform;
204
- if (platformFactory) {
205
- platform = platformFactory;
206
- } else {
207
- // Intentar import dinámico
208
- try {
209
- const platformModule = await _optionalImport('@angular/platform-browser-dynamic');
210
- platform = platformModule.platformBrowserDynamic;
211
- } catch (e) {
212
- // Intentar desde window
213
- if (window.ng?.platformBrowserDynamic) {
214
- platform = window.ng.platformBrowserDynamic;
215
- } else {
216
- throw new Error('platformBrowserDynamic not available. Please provide it via options.platformFactory');
217
- }
218
- }
219
- }
220
-
221
- // Bootstrap del módulo
222
- const platformRef = platform(providers);
223
- const moduleRef = await platformRef.bootstrapModule(AppModule);
224
-
225
- // Guardar referencias
226
- adapterState.apps.set(appName, {
227
- platformRef,
228
- moduleRef,
229
- container,
230
- rootElement: appElement
231
- });
232
-
233
- console.log(`[WuAngular] ✅ ${appName} mounted successfully`);
234
-
235
- if (onMount) {
236
- onMount(container, moduleRef);
237
- }
238
- } catch (error) {
239
- console.error(`[WuAngular] Mount error for ${appName}:`, error);
240
- throw error;
241
- }
242
- };
243
-
244
- // Función de unmount interna
245
- const unmountApp = async (container) => {
246
- const instance = adapterState.apps.get(appName);
247
-
248
- if (instance) {
249
- try {
250
- if (onUnmount) {
251
- onUnmount(instance.container, instance.moduleRef);
252
- }
253
-
254
- // Destruir el módulo
255
- if (instance.moduleRef) {
256
- instance.moduleRef.destroy();
257
- }
258
-
259
- // Destruir la plataforma
260
- if (instance.platformRef) {
261
- instance.platformRef.destroy();
262
- }
263
-
264
- // Limpiar DOM
265
- if (instance.rootElement && instance.rootElement.parentNode) {
266
- instance.rootElement.parentNode.removeChild(instance.rootElement);
267
- }
268
-
269
- adapterState.apps.delete(appName);
270
-
271
- console.log(`[WuAngular] ✅ ${appName} unmounted successfully`);
272
- } catch (error) {
273
- console.error(`[WuAngular] Unmount error for ${appName}:`, error);
274
- }
275
- }
276
-
277
- // Limpiar container si se proporciona
278
- if (container) {
279
- container.innerHTML = '';
280
- }
281
- };
282
-
283
- // Intentar registrar con Wu Framework
284
- try {
285
- const wu = await waitForWu(3000);
286
-
287
- wu.define(appName, {
288
- mount: mountApp,
289
- unmount: unmountApp
290
- });
291
-
292
- console.log(`[WuAngular] ✅ ${appName} registered with Wu Framework`);
293
- return true;
294
-
295
- } catch (error) {
296
- console.warn(`[WuAngular] Wu Framework not available for ${appName}`);
297
-
298
- // Modo standalone si está habilitado
299
- if (standalone) {
300
- const containerElement = document.querySelector(standaloneContainer);
301
-
302
- if (containerElement) {
303
- console.log(`[WuAngular] Running ${appName} in standalone mode`);
304
- await mountApp(containerElement);
305
- return true;
306
- } else {
307
- console.warn(`[WuAngular] Standalone container ${standaloneContainer} not found`);
308
- }
309
- }
310
-
311
- return false;
312
- }
313
- }
314
-
315
- /**
316
- * Registra un componente Angular standalone como microfrontend (Angular 14+)
317
- *
318
- * @param {string} appName - Nombre único del microfrontend
319
- * @param {Type<any>} RootComponent - Componente standalone principal
320
- * @param {Object} options - Opciones adicionales
321
- * @param {ApplicationConfig} options.appConfig - Configuración de la aplicación
322
- * @param {Function} options.onMount - Callback después de montar
323
- * @param {Function} options.onUnmount - Callback antes de desmontar
324
- * @param {boolean} options.standalone - Permitir ejecución standalone (default: true)
325
- * @param {string} options.standaloneContainer - Selector para modo standalone (default: '#root')
326
- * @param {Function} options.createApplication - createApplication from @angular/platform-browser (recommended to avoid bundler issues)
327
- * @param {Function} options.createComponent - createComponent from @angular/core
328
- * @param {Function} options.provideZoneChangeDetection - provideZoneChangeDetection from @angular/core
329
- *
330
- * @example
331
- * // Angular 14+ con standalone components
332
- * import { AppComponent } from './app/app.component';
333
- * import { createApplication } from '@angular/platform-browser';
334
- * import { createComponent, provideZoneChangeDetection } from '@angular/core';
335
- *
336
- * wuAngular.registerStandalone('my-app', AppComponent, {
337
- * createApplication,
338
- * createComponent,
339
- * provideZoneChangeDetection,
340
- * });
341
- */
342
- async function registerStandalone(appName, RootComponent, options = {}) {
343
- const {
344
- appConfig = {},
345
- onMount = null,
346
- onUnmount = null,
347
- standalone = true,
348
- standaloneContainer = '#root',
349
- createApplication: createApplicationOpt = null,
350
- createComponent: createComponentOpt = null,
351
- provideZoneChangeDetection: provideZoneChangeDetectionOpt = null
352
- } = options;
353
-
354
- // Función de mount para standalone components
355
- const mountApp = async (container) => {
356
- if (!container) {
357
- console.error(`[WuAngular] Mount failed for ${appName}: container is null`);
358
- return;
359
- }
360
-
361
- // Evitar doble mount
362
- if (adapterState.apps.has(appName)) {
363
- console.warn(`[WuAngular] ${appName} already mounted, unmounting first`);
364
- await unmountApp();
365
- }
366
-
367
- try {
368
- // Resolve Angular APIs: prefer options > dynamic import > window.ng
369
- let createApplicationFn = createApplicationOpt;
370
- let createComponentFn = createComponentOpt;
371
- let provideZoneChangeDetectionFn = provideZoneChangeDetectionOpt;
372
-
373
- if (!createApplicationFn) {
374
- try {
375
- const browserModule = await _optionalImport('@angular/platform-browser');
376
- createApplicationFn = browserModule.createApplication;
377
- const coreModule = await _optionalImport('@angular/core');
378
- createComponentFn = coreModule.createComponent;
379
- provideZoneChangeDetectionFn = coreModule.provideZoneChangeDetection;
380
- } catch (e) {
381
- if (window.ng?.createApplication) {
382
- createApplicationFn = window.ng.createApplication;
383
- createComponentFn = window.ng.createComponent;
384
- provideZoneChangeDetectionFn = window.ng.provideZoneChangeDetection;
385
- } else {
386
- throw new Error(
387
- 'Angular APIs not available. Pass createApplication, createComponent via options, ' +
388
- 'or ensure @angular/platform-browser is resolvable. See docs for example.'
389
- );
390
- }
391
- }
392
- }
393
-
394
- // Merge providers: add zone change detection if available
395
- const providers = [...(appConfig.providers || [])];
396
- if (provideZoneChangeDetectionFn) {
397
- providers.push(provideZoneChangeDetectionFn({ eventCoalescing: true }));
398
- }
399
-
400
- // Create Angular application
401
- const appRef = await createApplicationFn({ providers });
402
-
403
- // Create host element inside the container (Shadow DOM compatible)
404
- container.innerHTML = '';
405
- const selector = RootComponent.ɵcmp?.selectors?.[0]?.[0]
406
- || RootComponent.__annotations__?.[0]?.selector
407
- || 'app-root';
408
- const hostEl = document.createElement(selector);
409
- container.appendChild(hostEl);
410
-
411
- // Create and attach the component using hostElement (bypasses document.querySelector)
412
- const compRef = createComponentFn(RootComponent, {
413
- environmentInjector: appRef.injector,
414
- hostElement: hostEl,
415
- });
416
- appRef.attachView(compRef.hostView);
417
-
418
- // Guardar referencias
419
- adapterState.apps.set(appName, {
420
- appRef,
421
- compRef,
422
- container,
423
- hostElement: hostEl,
424
- isStandalone: true
425
- });
426
-
427
- console.log(`[WuAngular] ✅ ${appName} (standalone) mounted successfully`);
428
-
429
- if (onMount) {
430
- onMount(container, appRef);
431
- }
432
- } catch (error) {
433
- console.error(`[WuAngular] Mount error for ${appName}:`, error);
434
- throw error;
435
- }
436
- };
437
-
438
- // Función de unmount para standalone
439
- const unmountApp = async (container) => {
440
- const instance = adapterState.apps.get(appName);
441
-
442
- if (instance) {
443
- try {
444
- if (onUnmount) {
445
- onUnmount(instance.container, instance.appRef);
446
- }
447
-
448
- // Destruir el componente
449
- if (instance.compRef) {
450
- instance.compRef.destroy();
451
- }
452
-
453
- // Destruir la aplicación
454
- if (instance.appRef) {
455
- instance.appRef.destroy();
456
- }
457
-
458
- adapterState.apps.delete(appName);
459
-
460
- console.log(`[WuAngular] ✅ ${appName} (standalone) unmounted successfully`);
461
- } catch (error) {
462
- console.error(`[WuAngular] Unmount error for ${appName}:`, error);
463
- }
464
- }
465
-
466
- if (container) {
467
- container.innerHTML = '';
468
- }
469
- };
470
-
471
- // Intentar registrar con Wu Framework
472
- try {
473
- const wu = await waitForWu(3000);
474
-
475
- wu.define(appName, {
476
- mount: mountApp,
477
- unmount: unmountApp
478
- });
479
-
480
- console.log(`[WuAngular] ✅ ${appName} (standalone) registered with Wu Framework`);
481
- return true;
482
-
483
- } catch (error) {
484
- console.warn(`[WuAngular] Wu Framework not available for ${appName}`);
485
-
486
- if (standalone) {
487
- const containerElement = document.querySelector(standaloneContainer);
488
-
489
- if (containerElement) {
490
- console.log(`[WuAngular] Running ${appName} in standalone mode`);
491
- await mountApp(containerElement);
492
- return true;
493
- }
494
- }
495
-
496
- return false;
497
- }
498
- }
499
-
500
- /**
501
- * Register an Angular Elements (Web Component) as a microfrontend.
502
- * Requires @angular/elements to be installed.
503
- *
504
- * @param {string} appName - Unique microfrontend name
505
- * @param {Type<any>} Component - Angular standalone component
506
- * @param {Object} options
507
- * @param {string} options.elementTag - Custom element tag (default: `${appName}-element`)
508
- * @param {ApplicationConfig} options.appConfig - Angular application config
509
- * @param {Function} options.onMount - Called after mount
510
- * @param {Function} options.onUnmount - Called before unmount
511
- * @param {boolean} options.standalone - Allow standalone fallback (default: true)
512
- * @param {string} options.standaloneContainer - Selector for standalone mode (default: '#root')
513
- *
514
- * @example
515
- * import { wuAngular } from 'wu-framework/adapters/angular';
516
- * import { AppComponent } from './app/app.component';
517
- *
518
- * wuAngular.registerElement('mfe-angular', AppComponent, {
519
- * elementTag: 'mfe-angular-content',
520
- * });
521
- */
522
- async function registerElement(appName, Component, options = {}) {
523
- const {
524
- elementTag = `${appName}-element`,
525
- appConfig = {},
526
- onMount = null,
527
- onUnmount = null,
528
- standalone = true,
529
- standaloneContainer = '#root'
530
- } = options;
531
-
532
- let customElementRegistered = false;
533
-
534
- // Función para inicializar Angular Elements
535
- const initializeElement = async () => {
536
- if (customElementRegistered) return true;
537
-
538
- try {
539
- // Import dinámico de Angular
540
- const [{ createApplication }, { createCustomElement }] = await Promise.all([
541
- _optionalImport('@angular/platform-browser'),
542
- _optionalImport('@angular/elements')
543
- ]);
544
-
545
- // Crear aplicación Angular
546
- const app = await createApplication(appConfig);
547
-
548
- // Crear y registrar el custom element
549
- const CustomElement = createCustomElement(Component, { injector: app.injector });
550
-
551
- if (!customElements.get(elementTag)) {
552
- customElements.define(elementTag, CustomElement);
553
- console.log(`[WuAngular] ✅ Custom element registered: ${elementTag}`);
554
- }
555
-
556
- customElementRegistered = true;
557
-
558
- // Guardar referencia
559
- adapterState.apps.set(`${appName}:element`, {
560
- app,
561
- elementTag,
562
- CustomElement
563
- });
564
-
565
- return true;
566
- } catch (error) {
567
- console.error(`[WuAngular] Failed to initialize Angular Element:`, error);
568
- throw error;
569
- }
570
- };
571
-
572
- // Función de mount
573
- const mountApp = async (container) => {
574
- if (!container) {
575
- console.error(`[WuAngular] Mount failed for ${appName}: container is null`);
576
- return;
577
- }
578
-
579
- try {
580
- // Asegurar que el elemento está registrado
581
- await initializeElement();
582
-
583
- // Crear el elemento custom
584
- const element = document.createElement(elementTag);
585
- element.setAttribute('data-wu-angular-element', appName);
586
-
587
- // Limpiar y agregar al container
588
- container.innerHTML = '';
589
- container.appendChild(element);
590
-
591
- // Guardar referencia del mount
592
- adapterState.apps.set(appName, {
593
- element,
594
- container,
595
- elementTag
596
- });
597
-
598
- console.log(`[WuAngular] ✅ ${appName} (element) mounted successfully`);
599
-
600
- if (onMount) {
601
- onMount(container, element);
602
- }
603
-
604
- return element;
605
- } catch (error) {
606
- console.error(`[WuAngular] Mount error for ${appName}:`, error);
607
- throw error;
608
- }
609
- };
610
-
611
- // Función de unmount
612
- const unmountApp = async (container) => {
613
- const instance = adapterState.apps.get(appName);
614
-
615
- if (instance) {
616
- try {
617
- if (onUnmount) {
618
- onUnmount(instance.container, instance.element);
619
- }
620
-
621
- // Remover elemento del DOM
622
- if (instance.element && instance.element.parentNode) {
623
- instance.element.remove();
624
- }
625
-
626
- adapterState.apps.delete(appName);
627
-
628
- console.log(`[WuAngular] ✅ ${appName} (element) unmounted successfully`);
629
- } catch (error) {
630
- console.error(`[WuAngular] Unmount error for ${appName}:`, error);
631
- }
632
- }
633
-
634
- if (container) {
635
- container.innerHTML = '';
636
- }
637
- };
638
-
639
- // Intentar registrar con Wu Framework
640
- try {
641
- const wu = await waitForWu(3000);
642
-
643
- wu.define(appName, {
644
- mount: mountApp,
645
- unmount: unmountApp
646
- });
647
-
648
- console.log(`[WuAngular] ✅ ${appName} (element) registered with Wu Framework`);
649
- return true;
650
-
651
- } catch (error) {
652
- console.warn(`[WuAngular] Wu Framework not available for ${appName}`);
653
-
654
- if (standalone) {
655
- const containerElement = document.querySelector(standaloneContainer);
656
-
657
- if (containerElement) {
658
- console.log(`[WuAngular] Running ${appName} in standalone mode`);
659
- await mountApp(containerElement);
660
- return true;
661
- }
662
- }
663
-
664
- return false;
665
- }
666
- }
667
-
668
- /**
669
- * Creates a lightweight service for wu-framework events and store access.
670
- * Call destroy() in ngOnDestroy to clean up all subscriptions.
671
- *
672
- * @returns {{ emit, on, once, off, getState, setState, onStateChange, destroy, wu }}
673
- *
674
- * @example
675
- * import { createWuService } from 'wu-framework/adapters/angular';
676
- *
677
- * @Component({ selector: 'app-root', standalone: true, template: '...' })
678
- * export class AppComponent implements OnInit, OnDestroy {
679
- * private wu = createWuService();
680
- *
681
- * ngOnInit() {
682
- * this.wu.on('order:new', (e) => this.orders.push(e.data));
683
- * this.wu.onStateChange('theme.mode', (e) => this.theme = e.value);
684
- * const user = this.wu.getState('user');
685
- * }
686
- *
687
- * save() {
688
- * this.wu.setState('store.name', this.storeName);
689
- * this.wu.emit('settings:saved', { name: this.storeName });
690
- * }
691
- *
692
- * ngOnDestroy() {
693
- * this.wu.destroy(); // removes all on/onStateChange listeners
694
- * }
695
- * }
696
- */
697
- function createWuService() {
698
- const subscriptions = [];
699
-
700
- return {
701
- // Event Bus
702
- emit: (event, data, options) => {
703
- const wu = getWuInstance();
704
- if (wu?.eventBus) {
705
- wu.eventBus.emit(event, data, options);
706
- } else {
707
- console.warn('[WuService] Wu Framework not available');
708
- }
709
- },
710
-
711
- on: (event, callback) => {
712
- const wu = getWuInstance();
713
- if (wu?.eventBus) {
714
- const unsubscribe = wu.eventBus.on(event, callback);
715
- subscriptions.push(unsubscribe);
716
- return unsubscribe;
717
- }
718
- console.warn('[WuService] Wu Framework not available');
719
- return () => {};
720
- },
721
-
722
- once: (event, callback) => {
723
- const wu = getWuInstance();
724
- if (wu?.eventBus) {
725
- return wu.eventBus.once(event, callback);
726
- }
727
- return () => {};
728
- },
729
-
730
- off: (event, callback) => {
731
- const wu = getWuInstance();
732
- if (wu?.eventBus) {
733
- wu.eventBus.off(event, callback);
734
- }
735
- },
736
-
737
- // Store
738
- getState: (path) => {
739
- const wu = getWuInstance();
740
- return wu?.store?.get(path) || null;
741
- },
742
-
743
- setState: (path, value) => {
744
- const wu = getWuInstance();
745
- if (wu?.store) {
746
- wu.store.set(path, value);
747
- }
748
- },
749
-
750
- onStateChange: (pattern, callback) => {
751
- const wu = getWuInstance();
752
- if (wu?.store) {
753
- const unsubscribe = wu.store.on(pattern, callback);
754
- subscriptions.push(unsubscribe);
755
- return unsubscribe;
756
- }
757
- return () => {};
758
- },
759
-
760
- // Cleanup
761
- destroy: () => {
762
- subscriptions.forEach(unsub => unsub());
763
- subscriptions.length = 0;
764
- },
765
-
766
- // Access to raw Wu instance
767
- get wu() {
768
- return getWuInstance();
769
- }
770
- };
771
- }
772
-
773
- /**
774
- * Crea un componente Angular para cargar microfrontends (para el Shell)
775
- * Retorna la configuración del componente para ser usado con @Component
776
- *
777
- * @example
778
- * // wu-slot.component.ts
779
- * import { Component, Input, Output, EventEmitter } from '@angular/core';
780
- * import { createWuSlotComponent } from 'wu-framework/adapters/angular';
781
- *
782
- * const config = createWuSlotComponent();
783
- *
784
- * @Component({
785
- * selector: 'wu-slot',
786
- * template: config.template,
787
- * styles: config.styles
788
- * })
789
- * export class WuSlotComponent {
790
- * @Input() name!: string;
791
- * @Input() url!: string;
792
- * @Output() load = new EventEmitter();
793
- * @Output() error = new EventEmitter();
794
- *
795
- * // ... implement lifecycle methods from config.methods
796
- * }
797
- */
798
- function createWuSlotComponent() {
799
- return {
800
- selector: 'wu-slot',
801
-
802
- template: `
803
- <div
804
- #container
805
- class="wu-slot"
806
- [class.wu-slot-loading]="loading"
807
- [class.wu-slot-error]="error"
808
- [attr.data-wu-app]="name"
809
- [attr.data-wu-url]="url"
810
- style="min-height: 100px; position: relative;">
811
-
812
- <div *ngIf="error" class="wu-slot-error-message"
813
- style="padding: 1rem; border: 1px solid #f5c6cb; border-radius: 4px; background: #f8d7da; color: #721c24;">
814
- <strong>Error loading {{ name }}</strong>
815
- <p style="margin: 0.5rem 0 0 0;">{{ error }}</p>
816
- </div>
817
-
818
- <div *ngIf="loading && !error" class="wu-slot-loading-message"
819
- style="display: flex; align-items: center; justify-content: center; padding: 2rem; color: #666;">
820
- {{ fallbackText || 'Loading ' + name + '...' }}
821
- </div>
822
- </div>
823
- `,
824
-
825
- styles: [`
826
- .wu-slot {
827
- width: 100%;
828
- min-height: 100px;
829
- }
830
- `],
831
-
832
- // Métodos para implementar en el componente
833
- methods: {
834
- async ngOnInit() {
835
- await this.mountMicrofrontend();
836
- },
837
-
838
- ngOnDestroy() {
839
- this.unmountMicrofrontend();
840
- },
841
-
842
- async mountMicrofrontend() {
843
- try {
844
- this.loading = true;
845
- this.error = null;
846
-
847
- const wu = getWuInstance();
848
- if (!wu) {
849
- throw new Error('Wu Framework not initialized');
850
- }
851
-
852
- // Crear container único
853
- const containerId = `wu-slot-${this.name}-${Date.now()}`;
854
- const innerContainer = document.createElement('div');
855
- innerContainer.id = containerId;
856
- innerContainer.style.width = '100%';
857
- innerContainer.style.height = '100%';
858
-
859
- this.container.nativeElement.innerHTML = '';
860
- this.container.nativeElement.appendChild(innerContainer);
861
-
862
- // Crear y montar la app
863
- const app = wu.app(this.name, {
864
- url: this.url,
865
- container: `#${containerId}`,
866
- autoInit: true
867
- });
868
-
869
- this.appInstance = app;
870
- await app.mount();
871
-
872
- this.loading = false;
873
- this.load.emit({ name: this.name, url: this.url });
874
-
875
- } catch (err) {
876
- console.error(`[WuSlot] Error loading ${this.name}:`, err);
877
- this.error = err.message || 'Failed to load microfrontend';
878
- this.loading = false;
879
- this.errorEvent.emit(err);
880
- }
881
- },
882
-
883
- async unmountMicrofrontend() {
884
- if (this.appInstance) {
885
- try {
886
- await this.appInstance.unmount();
887
- } catch (err) {
888
- console.warn(`[WuSlot] Error unmounting ${this.name}:`, err);
889
- }
890
- this.appInstance = null;
891
- }
892
- }
893
- }
894
- };
895
- }
896
-
897
- /**
898
- * Helper para crear un módulo Angular que exporta WuSlotComponent
899
- * Útil para shells que quieren usar <wu-slot> directamente
900
- */
901
- function getWuSlotModuleConfig() {
902
- return {
903
- imports: ['CommonModule'],
904
- declarations: ['WuSlotComponent'],
905
- exports: ['WuSlotComponent']
906
- };
907
- }
908
-
909
- // ============================================
910
- // AI INTEGRATION (placeholder — ai.js loaded on demand)
911
- // ============================================
912
- function createWuAIService(...args) {
913
- throw new Error('[WuAngular] AI module not available. Install wu-framework AI extension.');
914
- }
915
-
916
- // Named exports for direct imports (e.g. import { createWuService } from 'wu-framework/adapters/angular')
917
- export { createWuService, register, registerStandalone, registerElement, createWuSlotComponent, getWuSlotModuleConfig, getWuInstance, waitForWu };
918
-
919
- // API pública del adapter
920
- export const wuAngular = {
921
- register,
922
- registerStandalone,
923
- registerElement,
924
- createWuService,
925
- createWuSlotComponent,
926
- getWuSlotModuleConfig,
927
- createWuAIService,
928
- getWuInstance,
929
- waitForWu
930
- };
931
-
932
- export default wuAngular;