wu-framework 1.0.0

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.
@@ -0,0 +1,316 @@
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
@@ -0,0 +1,192 @@
1
+ /**
2
+ * 🎯 WU-APP: SIMPLIFIED API WRAPPER
3
+ *
4
+ * Wrapper simple para uso declarativo de microfrontends
5
+ * Mantiene todo el core de wu-framework pero simplifica el uso
6
+ */
7
+
8
+ export class WuApp {
9
+ /**
10
+ * @param {string} name - Nombre de la app
11
+ * @param {Object} config - Configuración de la app
12
+ * @param {string} config.url - URL donde está corriendo la app
13
+ * @param {string} [config.container] - Selector del contenedor (opcional)
14
+ * @param {Object} wu - Instancia de WuCore
15
+ */
16
+ constructor(name, config, wu) {
17
+ this.name = name
18
+ this.url = config.url
19
+ this.container = config.container
20
+ this._wu = wu
21
+ this._mounted = false
22
+ this._autoInit = config.autoInit !== false // Default true
23
+
24
+ // Auto-register app in wu-framework
25
+ if (this._autoInit) {
26
+ this._registerApp()
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Registrar app en wu-framework
32
+ * @private
33
+ */
34
+ _registerApp() {
35
+ if (!this._wu.apps.has(this.name)) {
36
+ // Usar el método interno de wu-framework para registrar
37
+ this._wu.apps.set(this.name, {
38
+ name: this.name,
39
+ url: this.url,
40
+ status: 'registered'
41
+ })
42
+ console.log(`📦 App registered: ${this.name} at ${this.url}`)
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Montar la app en el contenedor
48
+ * @param {string} [container] - Selector del contenedor (opcional, usa config.container si no se pasa)
49
+ * @returns {Promise<void>}
50
+ */
51
+ async mount(container) {
52
+ const targetContainer = container || this.container
53
+
54
+ if (!targetContainer) {
55
+ throw new Error(`Container not specified for app: ${this.name}`)
56
+ }
57
+
58
+ // Asegurar que wu-framework está inicializado
59
+ if (!this._wu.initialized) {
60
+ await this._wu.init({
61
+ apps: [{ name: this.name, url: this.url }]
62
+ })
63
+ }
64
+
65
+ // Montar usando wu-framework core
66
+ await this._wu.mount(this.name, targetContainer)
67
+ this._mounted = true
68
+
69
+ return this
70
+ }
71
+
72
+ /**
73
+ * Desmontar la app
74
+ * @returns {Promise<void>}
75
+ */
76
+ async unmount() {
77
+ if (!this._mounted) {
78
+ console.warn(`⚠️ App ${this.name} is not mounted`)
79
+ return this
80
+ }
81
+
82
+ await this._wu.unmount(this.name)
83
+ this._mounted = false
84
+
85
+ return this
86
+ }
87
+
88
+ /**
89
+ * Remontar la app (útil para recargas)
90
+ * @param {string} [container] - Selector del contenedor
91
+ * @returns {Promise<void>}
92
+ */
93
+ async remount(container) {
94
+ await this.unmount()
95
+ await this.mount(container)
96
+ return this
97
+ }
98
+
99
+ /**
100
+ * Verificar si la app está montada
101
+ * @returns {boolean}
102
+ */
103
+ get isMounted() {
104
+ return this._mounted && this._wu.mounted?.has(this.name)
105
+ }
106
+
107
+ /**
108
+ * Obtener información de la app
109
+ * @returns {Object}
110
+ */
111
+ get info() {
112
+ return {
113
+ name: this.name,
114
+ url: this.url,
115
+ container: this.container,
116
+ mounted: this.isMounted,
117
+ status: this._wu.apps.get(this.name)?.status || 'unknown'
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Recargar la app (limpiar cache y remontar)
123
+ * @returns {Promise<void>}
124
+ */
125
+ async reload() {
126
+ console.log(`🔄 Reloading app: ${this.name}`)
127
+
128
+ await this.unmount()
129
+
130
+ // Limpiar caches
131
+ if (this._wu.loader?.clearCache) {
132
+ this._wu.loader.clearCache(this.name)
133
+ }
134
+ if (this._wu.manifest?.clearCache) {
135
+ this._wu.manifest.clearCache(this.name)
136
+ }
137
+
138
+ await this.mount()
139
+ console.log(`✅ App reloaded: ${this.name}`)
140
+
141
+ return this
142
+ }
143
+
144
+ /**
145
+ * Verificar el estado de la app
146
+ * @returns {Object}
147
+ */
148
+ async verify() {
149
+ const container = document.querySelector(this.container)
150
+ const hasShadowDOM = container?.shadowRoot !== null
151
+ const hasContent = (container?.shadowRoot?.children?.length || 0) > 0
152
+
153
+ return {
154
+ name: this.name,
155
+ mounted: this.isMounted,
156
+ container: {
157
+ found: !!container,
158
+ selector: this.container,
159
+ hasShadowDOM,
160
+ hasContent
161
+ },
162
+ wu: {
163
+ registered: this._wu.apps.has(this.name),
164
+ mountedInWu: this._wu.mounted?.has(this.name)
165
+ }
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Shorthand para mount
171
+ */
172
+ async start(container) {
173
+ return await this.mount(container)
174
+ }
175
+
176
+ /**
177
+ * Shorthand para unmount
178
+ */
179
+ async stop() {
180
+ return await this.unmount()
181
+ }
182
+
183
+ /**
184
+ * Destruir la app completamente
185
+ */
186
+ async destroy() {
187
+ await this.unmount()
188
+ this._wu.apps.delete(this.name)
189
+ this._mounted = false
190
+ console.log(`🗑️ App destroyed: ${this.name}`)
191
+ }
192
+ }