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,271 @@
1
+ /**
2
+ * 🚀 WU-LOADER: SISTEMA DE CARGA DINÁMICA UNIVERSAL
3
+ * Carga aplicaciones y componentes sin depender del framework
4
+ */
5
+
6
+ export class WuLoader {
7
+ constructor() {
8
+ this.cache = new Map();
9
+ this.loadingPromises = new Map();
10
+
11
+ console.log('[WuLoader] 📦 Dynamic loader initialized');
12
+ }
13
+
14
+ /**
15
+ * Cargar aplicación completa
16
+ * @param {string} appUrl - URL base de la aplicación
17
+ * @param {Object} manifest - Manifest de la aplicación
18
+ * @returns {string} Código JavaScript de la aplicación
19
+ */
20
+ async loadApp(appUrl, manifest) {
21
+ const entryFile = manifest?.entry || 'index.js';
22
+ const fullUrl = `${appUrl}/${entryFile}`;
23
+
24
+ console.log(`[WuLoader] 📥 Loading app from: ${fullUrl}`);
25
+
26
+ try {
27
+ // Verificar cache
28
+ if (this.cache.has(fullUrl)) {
29
+ console.log(`[WuLoader] ⚡ Cache hit for: ${fullUrl}`);
30
+ return this.cache.get(fullUrl);
31
+ }
32
+
33
+ // Verificar si ya está cargando
34
+ if (this.loadingPromises.has(fullUrl)) {
35
+ console.log(`[WuLoader] ⏳ Loading in progress for: ${fullUrl}`);
36
+ return await this.loadingPromises.get(fullUrl);
37
+ }
38
+
39
+ // Crear promesa de carga
40
+ const loadingPromise = this.fetchCode(fullUrl);
41
+ this.loadingPromises.set(fullUrl, loadingPromise);
42
+
43
+ const code = await loadingPromise;
44
+
45
+ // Limpiar promesa de carga y cachear resultado
46
+ this.loadingPromises.delete(fullUrl);
47
+ this.cache.set(fullUrl, code);
48
+
49
+ console.log(`[WuLoader] ✅ App loaded successfully: ${fullUrl}`);
50
+ return code;
51
+
52
+ } catch (error) {
53
+ this.loadingPromises.delete(fullUrl);
54
+ console.error(`[WuLoader] ❌ Failed to load app: ${fullUrl}`, error);
55
+ throw new Error(`Failed to load app from ${fullUrl}: ${error.message}`);
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Cargar componente específico
61
+ * @param {string} appUrl - URL base de la aplicación
62
+ * @param {string} componentPath - Ruta del componente
63
+ * @returns {Function} Función del componente
64
+ */
65
+ async loadComponent(appUrl, componentPath) {
66
+ // Normalizar ruta del componente
67
+ let normalizedPath = componentPath;
68
+ if (normalizedPath.startsWith('./')) {
69
+ normalizedPath = normalizedPath.substring(2);
70
+ }
71
+ if (!normalizedPath.endsWith('.js') && !normalizedPath.endsWith('.jsx')) {
72
+ normalizedPath += '.js';
73
+ }
74
+
75
+ const fullUrl = `${appUrl}/${normalizedPath}`;
76
+
77
+ console.log(`[WuLoader] 🧩 Loading component from: ${fullUrl}`);
78
+
79
+ try {
80
+ // Cargar código del componente
81
+ const code = await this.loadCode(fullUrl);
82
+
83
+ // Crear función que retorna el componente
84
+ const componentFunction = new Function('require', 'module', 'exports', `
85
+ ${code}
86
+ return typeof module.exports === 'function' ? module.exports :
87
+ typeof module.exports === 'object' && module.exports.default ? module.exports.default :
88
+ exports.default || exports;
89
+ `);
90
+
91
+ // Ejecutar y obtener el componente
92
+ const fakeModule = { exports: {} };
93
+ const fakeRequire = (name) => {
94
+ console.warn(`[WuLoader] Component ${componentPath} requires ${name} - not supported yet`);
95
+ return {};
96
+ };
97
+
98
+ const component = componentFunction(fakeRequire, fakeModule, fakeModule.exports);
99
+
100
+ console.log(`[WuLoader] ✅ Component loaded: ${componentPath}`);
101
+ return component;
102
+
103
+ } catch (error) {
104
+ console.error(`[WuLoader] ❌ Failed to load component: ${componentPath}`, error);
105
+ throw new Error(`Failed to load component ${componentPath}: ${error.message}`);
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Cargar código con cache
111
+ * @param {string} url - URL del archivo
112
+ * @returns {string} Código JavaScript
113
+ */
114
+ async loadCode(url) {
115
+ // Verificar cache
116
+ if (this.cache.has(url)) {
117
+ return this.cache.get(url);
118
+ }
119
+
120
+ // Verificar si ya está cargando
121
+ if (this.loadingPromises.has(url)) {
122
+ return await this.loadingPromises.get(url);
123
+ }
124
+
125
+ // Crear promesa de carga
126
+ const loadingPromise = this.fetchCode(url);
127
+ this.loadingPromises.set(url, loadingPromise);
128
+
129
+ try {
130
+ const code = await loadingPromise;
131
+ this.loadingPromises.delete(url);
132
+ this.cache.set(url, code);
133
+ return code;
134
+ } catch (error) {
135
+ this.loadingPromises.delete(url);
136
+ throw error;
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Realizar fetch del código
142
+ * @param {string} url - URL del archivo
143
+ * @returns {string} Código JavaScript
144
+ */
145
+ async fetchCode(url) {
146
+ const response = await fetch(url, {
147
+ cache: 'no-cache',
148
+ headers: {
149
+ 'Accept': 'application/javascript, text/javascript, */*'
150
+ }
151
+ });
152
+
153
+ if (!response.ok) {
154
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
155
+ }
156
+
157
+ const code = await response.text();
158
+
159
+ if (!code.trim()) {
160
+ throw new Error('Empty response');
161
+ }
162
+
163
+ return code;
164
+ }
165
+
166
+ /**
167
+ * Precargar aplicaciones
168
+ * @param {Array} appConfigs - Configuraciones de aplicaciones
169
+ */
170
+ async preload(appConfigs) {
171
+ console.log(`[WuLoader] 🚀 Preloading ${appConfigs.length} apps...`);
172
+
173
+ const preloadPromises = appConfigs.map(async (config) => {
174
+ try {
175
+ await this.loadApp(config.url, config.manifest);
176
+ console.log(`[WuLoader] ✅ Preloaded: ${config.name}`);
177
+ } catch (error) {
178
+ console.warn(`[WuLoader] ⚠️ Failed to preload ${config.name}:`, error.message);
179
+ }
180
+ });
181
+
182
+ await Promise.allSettled(preloadPromises);
183
+ console.log(`[WuLoader] 🎉 Preload completed`);
184
+ }
185
+
186
+ /**
187
+ * Verificar si una URL está disponible
188
+ * @param {string} url - URL a verificar
189
+ * @returns {boolean} True si está disponible
190
+ */
191
+ async isAvailable(url) {
192
+ try {
193
+ const response = await fetch(url, { method: 'HEAD' });
194
+ return response.ok;
195
+ } catch {
196
+ return false;
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Resolver dependencias de imports
202
+ * @param {Array} imports - Lista de imports del manifest
203
+ * @param {Map} availableApps - Apps disponibles
204
+ */
205
+ async resolveDependencies(imports, availableApps) {
206
+ const resolved = new Map();
207
+
208
+ for (const importPath of imports || []) {
209
+ const [appName, componentName] = importPath.split('.');
210
+
211
+ if (!appName || !componentName) {
212
+ console.warn(`[WuLoader] Invalid import format: ${importPath}`);
213
+ continue;
214
+ }
215
+
216
+ const app = availableApps.get(appName);
217
+ if (!app) {
218
+ console.warn(`[WuLoader] Import app not found: ${appName}`);
219
+ continue;
220
+ }
221
+
222
+ const manifest = app.manifest;
223
+ const exportPath = manifest?.wu?.exports?.[componentName];
224
+
225
+ if (!exportPath) {
226
+ console.warn(`[WuLoader] Export not found: ${importPath}`);
227
+ continue;
228
+ }
229
+
230
+ try {
231
+ const component = await this.loadComponent(app.url, exportPath);
232
+ resolved.set(importPath, component);
233
+ console.log(`[WuLoader] ✅ Resolved dependency: ${importPath}`);
234
+ } catch (error) {
235
+ console.error(`[WuLoader] ❌ Failed to resolve: ${importPath}`, error);
236
+ }
237
+ }
238
+
239
+ return resolved;
240
+ }
241
+
242
+ /**
243
+ * Limpiar cache
244
+ * @param {string} pattern - Patrón opcional para limpiar URLs específicas
245
+ */
246
+ clearCache(pattern) {
247
+ if (pattern) {
248
+ const regex = new RegExp(pattern);
249
+ for (const [url] of this.cache) {
250
+ if (regex.test(url)) {
251
+ this.cache.delete(url);
252
+ console.log(`[WuLoader] 🗑️ Cleared cache for: ${url}`);
253
+ }
254
+ }
255
+ } else {
256
+ this.cache.clear();
257
+ console.log(`[WuLoader] 🗑️ Cache cleared completely`);
258
+ }
259
+ }
260
+
261
+ /**
262
+ * Obtener estadísticas del loader
263
+ */
264
+ getStats() {
265
+ return {
266
+ cached: this.cache.size,
267
+ loading: this.loadingPromises.size,
268
+ cacheKeys: Array.from(this.cache.keys())
269
+ };
270
+ }
271
+ }
@@ -0,0 +1,119 @@
1
+ /**
2
+ * 📝 WU-LOGGER: Sistema de logging inteligente para entornos
3
+ * Controla los logs automáticamente según el entorno
4
+ */
5
+
6
+ export class WuLogger {
7
+ constructor() {
8
+ // Detectar entorno automáticamente
9
+ this.isDevelopment = this.detectEnvironment();
10
+ this.logLevel = this.isDevelopment ? 'debug' : 'error';
11
+
12
+ this.levels = {
13
+ debug: 0,
14
+ info: 1,
15
+ warn: 2,
16
+ error: 3,
17
+ silent: 4
18
+ };
19
+ }
20
+
21
+ /**
22
+ * Detectar si estamos en desarrollo
23
+ */
24
+ detectEnvironment() {
25
+ // Múltiples formas de detectar desarrollo
26
+ return (
27
+ // Vite development
28
+ window.location.hostname === 'localhost' ||
29
+ window.location.hostname === '127.0.0.1' ||
30
+ window.location.port !== '' ||
31
+ // NODE_ENV si está disponible
32
+ (typeof process !== 'undefined' && process.env?.NODE_ENV === 'development') ||
33
+ // URL params para forzar debug
34
+ new URLSearchParams(window.location.search).has('wu-debug') ||
35
+ // Manual override
36
+ window.WU_DEBUG === true
37
+ );
38
+ }
39
+
40
+ /**
41
+ * Configurar nivel de logging
42
+ */
43
+ setLevel(level) {
44
+ this.logLevel = level;
45
+ return this;
46
+ }
47
+
48
+ /**
49
+ * Habilitar/deshabilitar development mode
50
+ */
51
+ setDevelopment(isDev) {
52
+ this.isDevelopment = isDev;
53
+ this.logLevel = isDev ? 'debug' : 'error';
54
+ return this;
55
+ }
56
+
57
+ /**
58
+ * Verificar si debemos mostrar el log
59
+ */
60
+ shouldLog(level) {
61
+ return this.levels[level] >= this.levels[this.logLevel];
62
+ }
63
+
64
+ /**
65
+ * Logging methods
66
+ */
67
+ debug(...args) {
68
+ if (this.shouldLog('debug')) {
69
+ console.log(...args);
70
+ }
71
+ }
72
+
73
+ info(...args) {
74
+ if (this.shouldLog('info')) {
75
+ console.info(...args);
76
+ }
77
+ }
78
+
79
+ warn(...args) {
80
+ if (this.shouldLog('warn')) {
81
+ console.warn(...args);
82
+ }
83
+ }
84
+
85
+ error(...args) {
86
+ if (this.shouldLog('error')) {
87
+ console.error(...args);
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Logging con contexto Wu
93
+ */
94
+ wu(level, ...args) {
95
+ if (this.shouldLog(level)) {
96
+ const method = level === 'debug' ? 'log' : level;
97
+ console[method]('[Wu]', ...args);
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Helper methods específicos para Wu
103
+ */
104
+ wuDebug(...args) { this.wu('debug', ...args); }
105
+ wuInfo(...args) { this.wu('info', ...args); }
106
+ wuWarn(...args) { this.wu('warn', ...args); }
107
+ wuError(...args) { this.wu('error', ...args); }
108
+ }
109
+
110
+ // Singleton instance
111
+ export const logger = new WuLogger();
112
+
113
+ // Helper para compatibilidad con logs existentes
114
+ export const wuLog = {
115
+ debug: (...args) => logger.wuDebug(...args),
116
+ info: (...args) => logger.wuInfo(...args),
117
+ warn: (...args) => logger.wuWarn(...args),
118
+ error: (...args) => logger.wuError(...args)
119
+ };