wu-framework 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wu-framework",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "🚀 Universal Microfrontends Framework - Framework agnostic, zero config, Shadow DOM isolation",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -7,7 +7,8 @@ export class WuLogger {
7
7
  constructor() {
8
8
  // Detectar entorno automáticamente
9
9
  this.isDevelopment = this.detectEnvironment();
10
- this.logLevel = this.isDevelopment ? 'debug' : 'error';
10
+ // En desarrollo: warn (menos ruido), en producción: error
11
+ this.logLevel = this.isDevelopment ? 'warn' : 'error';
11
12
 
12
13
  this.levels = {
13
14
  debug: 0,
@@ -116,4 +117,19 @@ export const wuLog = {
116
117
  info: (...args) => logger.wuInfo(...args),
117
118
  warn: (...args) => logger.wuWarn(...args),
118
119
  error: (...args) => logger.wuError(...args)
119
- };
120
+ };
121
+
122
+ /**
123
+ * 🔇 Silenciar todos los logs de Wu Framework
124
+ * Útil en producción para eliminar todo el ruido
125
+ */
126
+ export function silenceAllLogs() {
127
+ logger.setLevel('silent');
128
+ }
129
+
130
+ /**
131
+ * 🔊 Restaurar logs (nivel debug)
132
+ */
133
+ export function enableAllLogs() {
134
+ logger.setLevel('debug');
135
+ }
@@ -1,52 +1,21 @@
1
1
  /**
2
- * 🔔 WU-REGISTRY: EVENT-BASED APP REGISTRATION SYSTEM
3
- *
4
- * Reemplaza el polling con Custom Events para mejor performance
2
+ * 🔔 WU-REGISTRY: APP REGISTRATION TRACKER
3
+ * Simplificado - solo trackea apps registradas
5
4
  */
6
5
 
7
6
  export class WuRegistry {
8
7
  constructor() {
9
8
  this.registeredApps = new Set();
10
- this.waitingPromises = new Map();
11
-
12
- // Event listeners para registro
13
- this.setupEventListeners();
14
-
15
- console.log('[WuRegistry] 🔔 Event-based registration system initialized');
16
- }
17
-
18
- /**
19
- * 📡 SETUP EVENT LISTENERS
20
- */
21
- setupEventListeners() {
22
- // Escuchar eventos de registro de apps
23
- window.addEventListener('wu:app:ready', (event) => {
24
- const { appName } = event.detail;
25
- console.log(`[WuRegistry] ✅ App registered via event: ${appName}`);
26
-
27
- this.registeredApps.add(appName);
28
-
29
- // Resolver promesas pendientes
30
- if (this.waitingPromises.has(appName)) {
31
- const { resolve } = this.waitingPromises.get(appName);
32
- resolve();
33
- this.waitingPromises.delete(appName);
34
- }
35
- });
36
-
37
- // API para que apps notifiquen que están listas (se agrega a window.wu cuando exista)
38
- // No crear window.wu aquí - eso lo hace index.js con la instancia completa
39
9
  this._setupNotifyReady();
40
10
  }
41
11
 
42
12
  /**
43
- * 🔔 Setup notifyReady API cuando window.wu esté disponible
13
+ * 🔔 Setup notifyReady API en window.wu
44
14
  */
45
15
  _setupNotifyReady() {
46
16
  const setupFn = () => {
47
17
  if (window.wu && !window.wu.notifyReady) {
48
18
  window.wu.notifyReady = (appName) => {
49
- console.log(`[WuRegistry] 📢 App ${appName} called notifyReady()`);
50
19
  const event = new CustomEvent('wu:app:ready', {
51
20
  detail: { appName, timestamp: Date.now() }
52
21
  });
@@ -55,89 +24,37 @@ export class WuRegistry {
55
24
  }
56
25
  };
57
26
 
58
- // Intentar setup inmediato
59
27
  setupFn();
60
-
61
- // Si window.wu no existe aún, esperar un tick
62
28
  if (!window.wu) {
63
29
  queueMicrotask(setupFn);
64
30
  }
65
31
  }
66
32
 
67
33
  /**
68
- * WAIT FOR APP: Promise-based waiting
69
- * @param {string} appName - Nombre de la app
70
- * @param {number} timeout - Timeout en ms (default: 10000)
71
- * @returns {Promise}
34
+ * MARK AS REGISTERED
72
35
  */
73
- waitForApp(appName, timeout = 10000) {
74
- // Si ya está registrada, resolver inmediatamente
75
- if (this.registeredApps.has(appName)) {
76
- console.log(`[WuRegistry] ⚡ App ${appName} already registered`);
77
- return Promise.resolve();
78
- }
79
-
80
- console.log(`[WuRegistry] ⏳ Waiting for app ${appName} to register...`);
81
-
82
- return new Promise((resolve, reject) => {
83
- // Guardar promesa
84
- this.waitingPromises.set(appName, { resolve, reject });
85
-
86
- // Timeout
87
- const timeoutId = setTimeout(() => {
88
- if (this.waitingPromises.has(appName)) {
89
- this.waitingPromises.delete(appName);
90
-
91
- const error = new Error(
92
- `App '${appName}' failed to register within ${timeout}ms.\n\n` +
93
- `Possible causes:\n` +
94
- ` - Module failed to load\n` +
95
- ` - wu.define() was not called\n` +
96
- ` - Check browser console for import errors\n\n` +
97
- `Make sure your app calls:\n` +
98
- ` wu.define('${appName}', { mount, unmount })`
99
- );
100
-
101
- reject(error);
102
- }
103
- }, timeout);
104
-
105
- // Limpiar timeout cuando se resuelva
106
- this.waitingPromises.get(appName).timeoutId = timeoutId;
107
- });
36
+ markAsRegistered(appName) {
37
+ this.registeredApps.add(appName);
108
38
  }
109
39
 
110
40
  /**
111
- * MARK AS REGISTERED
112
- * @param {string} appName
41
+ * IS REGISTERED
113
42
  */
114
- markAsRegistered(appName) {
115
- this.registeredApps.add(appName);
116
- console.log(`[WuRegistry] ✅ App ${appName} marked as registered`);
43
+ isRegistered(appName) {
44
+ return this.registeredApps.has(appName);
117
45
  }
118
46
 
119
47
  /**
120
48
  * ❌ UNREGISTER APP
121
- * @param {string} appName
122
49
  */
123
50
  unregister(appName) {
124
51
  this.registeredApps.delete(appName);
125
- console.log(`[WuRegistry] ❌ App ${appName} unregistered`);
126
52
  }
127
53
 
128
54
  /**
129
55
  * 🧹 CLEANUP
130
56
  */
131
57
  cleanup() {
132
- // Rechazar todas las promesas pendientes
133
- for (const [appName, { reject, timeoutId }] of this.waitingPromises) {
134
- clearTimeout(timeoutId);
135
- reject(new Error(`Registry cleanup: ${appName}`));
136
- }
137
-
138
- this.waitingPromises.clear();
139
58
  this.registeredApps.clear();
140
-
141
- console.log('[WuRegistry] 🧹 Registry cleaned up');
142
59
  }
143
60
  }
package/src/index.js CHANGED
@@ -103,7 +103,7 @@ if (typeof window !== 'undefined') {
103
103
 
104
104
  // Configurar propiedades si no existen
105
105
  if (!wu.version) {
106
- wu.version = '1.0.4';
106
+ wu.version = '1.0.5';
107
107
  console.log('🚀 Wu Framework loaded - Universal Microfrontends ready');
108
108
  wu.info = {
109
109
  name: 'Wu Framework',
@@ -126,6 +126,19 @@ if (typeof window !== 'undefined') {
126
126
  wu.once = (eventName, callback) => wu.eventBus.once(eventName, callback);
127
127
  wu.off = (eventName, callback) => wu.eventBus.off(eventName, callback);
128
128
  }
129
+
130
+ // 🔇 Exponer funciones de control de logs
131
+ // window.wu.silence() para silenciar, window.wu.verbose() para debug
132
+ if (!wu.silence) {
133
+ wu.silence = async () => {
134
+ const { silenceAllLogs } = await import('./core/wu-logger.js');
135
+ silenceAllLogs();
136
+ };
137
+ wu.verbose = async () => {
138
+ const { enableAllLogs } = await import('./core/wu-logger.js');
139
+ enableAllLogs();
140
+ };
141
+ }
129
142
  }
130
143
 
131
144
  // Exportar API principal
@@ -167,6 +180,7 @@ export {
167
180
  } from './core/wu-hooks.js';
168
181
  export { WuSandboxPool } from './core/wu-sandbox-pool.js';
169
182
  export { WuRegistry } from './core/wu-registry.js';
183
+ export { silenceAllLogs, enableAllLogs } from './core/wu-logger.js';
170
184
 
171
185
  /**
172
186
  * Utilidades de conveniencia para uso común
@@ -1,316 +0,0 @@
1
- /**
2
- * 🚀 WU-FRAMEWORK SIMPLIFIED API
3
- * Developer-friendly interface for universal microfrontends
4
- */
5
-
6
- import { wu as wuCore } from '../index.js'
7
- import { logger } from '../core/wu-logger.js'
8
-
9
- class WuSimpleAPI {
10
- constructor() {
11
- this.core = wuCore
12
- this.autoInitialized = false
13
- this.defaultConfig = {
14
- container: '#app',
15
- mode: 'auto', // auto, spa, microfrontend
16
- debug: false,
17
- timeout: 30000,
18
- retries: 3
19
- }
20
- }
21
-
22
- /**
23
- * 🌟 SMART MOUNT: Intelligent mounting with auto-discovery
24
- * wu.mount('dashboard').into('#container')
25
- * wu.mount('http://localhost:3001/dashboard')
26
- */
27
- mount(appNameOrUrl) {
28
- const mountAPI = {
29
- into: async (containerSelector = this.defaultConfig.container) => {
30
- await this._ensureInitialized()
31
-
32
- // 🔍 Detect if it's a URL or app name
33
- if (this._isUrl(appNameOrUrl)) {
34
- return await this._mountFromUrl(appNameOrUrl, containerSelector)
35
- } else {
36
- return await this._mountFromName(appNameOrUrl, containerSelector)
37
- }
38
- }
39
- }
40
-
41
- // Support direct call: wu.mount('dashboard', '#container')
42
- if (typeof arguments[1] === 'string') {
43
- return mountAPI.into(arguments[1])
44
- }
45
-
46
- return mountAPI
47
- }
48
-
49
- /**
50
- * 🚀 QUICK LOAD: One-liner for loading remote microfrontends
51
- * wu.load('http://localhost:3001/dashboard')
52
- * wu.load('http://localhost:3001', { name: 'dashboard' })
53
- */
54
- async load(url, options = {}) {
55
- await this._ensureInitialized()
56
-
57
- const appName = options.name || this._extractAppName(url)
58
- const container = options.container || this.defaultConfig.container
59
-
60
- // Auto-register and mount
61
- await this._registerFromUrl(url, appName)
62
- return await this.mount(appName).into(container)
63
- }
64
-
65
- /**
66
- * 🎯 BATCH OPERATIONS: Load multiple apps at once
67
- * wu.loadMany([
68
- * { name: 'dashboard', url: 'http://localhost:3001' },
69
- * { name: 'sidebar', url: 'http://localhost:3002' }
70
- * ])
71
- */
72
- async loadMany(apps) {
73
- await this._ensureInitialized()
74
-
75
- const results = []
76
- for (const app of apps) {
77
- try {
78
- await this._registerFromUrl(app.url, app.name)
79
- results.push({ name: app.name, status: 'registered' })
80
- } catch (error) {
81
- results.push({ name: app.name, status: 'failed', error: error.message })
82
- }
83
- }
84
-
85
- return results
86
- }
87
-
88
- /**
89
- * 🔧 CONFIGURATION: Flexible configuration methods
90
- * wu.config({ debug: true, timeout: 60000 })
91
- * wu.debug(true)
92
- * wu.timeout(30000)
93
- */
94
- config(options = {}) {
95
- Object.assign(this.defaultConfig, options)
96
-
97
- if (options.debug) {
98
- logger.wuDebug('🔧 Configuration updated:', this.defaultConfig)
99
- }
100
-
101
- return this
102
- }
103
-
104
- /**
105
- * 🐛 DEBUG MODE: Quick debug toggle
106
- * wu.debug(true)
107
- * wu.debug() // toggle
108
- */
109
- debug(enabled) {
110
- if (enabled === undefined) {
111
- this.defaultConfig.debug = !this.defaultConfig.debug
112
- } else {
113
- this.defaultConfig.debug = !!enabled
114
- }
115
-
116
- logger.wuInfo(`🐛 Debug mode: ${this.defaultConfig.debug ? 'ON' : 'OFF'}`)
117
- return this
118
- }
119
-
120
- /**
121
- * ⏱️ TIMEOUT: Set operation timeout
122
- * wu.timeout(60000) // 60 seconds
123
- */
124
- timeout(ms) {
125
- this.defaultConfig.timeout = ms
126
- logger.wuDebug(`⏱️ Timeout set to ${ms}ms`)
127
- return this
128
- }
129
-
130
- /**
131
- * 🔄 RETRIES: Set retry attempts
132
- * wu.retries(5)
133
- */
134
- retries(count) {
135
- this.defaultConfig.retries = count
136
- logger.wuDebug(`🔄 Retries set to ${count}`)
137
- return this
138
- }
139
-
140
- /**
141
- * 🎯 DEFAULT CONTAINER: Set default mounting container
142
- * wu.container('#main-app')
143
- */
144
- container(selector) {
145
- this.defaultConfig.container = selector
146
- logger.wuDebug(`🎯 Default container set to ${selector}`)
147
- return this
148
- }
149
-
150
- /**
151
- * 🌐 GLOBAL SETTINGS: Environment-based configuration
152
- * wu.development() // Sets debug: true, retries: 1
153
- * wu.production() // Sets debug: false, retries: 3
154
- */
155
- development() {
156
- return this.config({
157
- debug: true,
158
- retries: 1,
159
- timeout: 60000
160
- })
161
- }
162
-
163
- production() {
164
- return this.config({
165
- debug: false,
166
- retries: 3,
167
- timeout: 30000
168
- })
169
- }
170
-
171
- /**
172
- * 🚀 QUICK SETUP: Common configurations
173
- * wu.spa() // Single Page App mode
174
- * wu.micro() // Microfrontend mode
175
- */
176
- spa() {
177
- return this.config({
178
- mode: 'spa',
179
- container: '#app',
180
- debug: false
181
- })
182
- }
183
-
184
- micro() {
185
- return this.config({
186
- mode: 'microfrontend',
187
- debug: true,
188
- retries: 5
189
- })
190
- }
191
-
192
- /**
193
- * 📊 STATUS: Get framework and apps status
194
- * wu.status()
195
- */
196
- status() {
197
- const stats = this.core.getStats?.() || {}
198
-
199
- return {
200
- initialized: this.autoInitialized,
201
- apps: {
202
- registered: stats.registered || 0,
203
- mounted: stats.mounted || 0,
204
- available: stats.apps || []
205
- },
206
- health: this.core.quantumState?.dimensionalStability || 'unknown',
207
- config: this.defaultConfig
208
- }
209
- }
210
-
211
- /**
212
- * 🧹 CLEANUP: Clean shutdown
213
- * wu.destroy()
214
- */
215
- async destroy() {
216
- if (this.core.destroy) {
217
- await this.core.destroy()
218
- }
219
- this.autoInitialized = false
220
- logger.wuInfo('🧹 Framework destroyed')
221
- }
222
-
223
-
224
- // 🔒 PRIVATE METHODS
225
-
226
- async _ensureInitialized() {
227
- if (!this.autoInitialized) {
228
- await this._autoInitialize()
229
- }
230
- }
231
-
232
- async _autoInitialize() {
233
- if (this.defaultConfig.debug) {
234
- logger.wuDebug('🚀 Auto-initializing Wu Framework...')
235
- }
236
-
237
- // Smart initialization with minimal config
238
- await this.core.init({ apps: [] })
239
- this.autoInitialized = true
240
-
241
- if (this.defaultConfig.debug) {
242
- logger.wuDebug('✅ Wu Framework auto-initialized')
243
- }
244
- }
245
-
246
- _isUrl(str) {
247
- try {
248
- new URL(str)
249
- return true
250
- } catch {
251
- return str.includes('://') || str.startsWith('http')
252
- }
253
- }
254
-
255
- _extractAppName(url) {
256
- try {
257
- const urlObj = new URL(url)
258
- const pathSegments = urlObj.pathname.split('/').filter(Boolean)
259
- return pathSegments[pathSegments.length - 1] || urlObj.hostname.split('.')[0]
260
- } catch {
261
- return 'app-' + Date.now()
262
- }
263
- }
264
-
265
- async _registerFromUrl(url, appName) {
266
- const baseUrl = this._getBaseUrl(url)
267
-
268
- await this.core.registerApp({
269
- name: appName,
270
- url: baseUrl
271
- })
272
- }
273
-
274
- _getBaseUrl(url) {
275
- try {
276
- const urlObj = new URL(url)
277
- return `${urlObj.protocol}//${urlObj.host}`
278
- } catch {
279
- return url
280
- }
281
- }
282
-
283
- async _mountFromUrl(url, containerSelector) {
284
- const appName = this._extractAppName(url)
285
- await this._registerFromUrl(url, appName)
286
- return await this._mountFromName(appName, containerSelector)
287
- }
288
-
289
- async _mountFromName(appName, containerSelector) {
290
- try {
291
- await this.core.mount(appName, containerSelector)
292
-
293
- if (this.defaultConfig.debug) {
294
- logger.wuDebug(`✅ ${appName} mounted successfully in ${containerSelector}`)
295
- }
296
-
297
- return {
298
- app: appName,
299
- container: containerSelector,
300
- status: 'mounted',
301
- unmount: () => this.core.unmount(appName)
302
- }
303
-
304
- } catch (error) {
305
- console.error(`[Wu] ❌ Failed to mount ${appName}:`, error.message)
306
- throw new Error(`Failed to mount ${appName}: ${error.message}`)
307
- }
308
- }
309
- }
310
-
311
- // 🌟 Create singleton instance
312
- const wuSimple = new WuSimpleAPI()
313
-
314
- // 🎯 Export simple API
315
- export { wuSimple as wu }
316
- export default wuSimple