wu-framework 1.1.15 → 1.1.17

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 (88) hide show
  1. package/README.md +52 -20
  2. package/dist/wu-framework.cjs.js +1 -1
  3. package/dist/wu-framework.cjs.js.map +1 -1
  4. package/dist/wu-framework.dev.js +15511 -15146
  5. package/dist/wu-framework.dev.js.map +1 -1
  6. package/dist/wu-framework.esm.js +1 -1
  7. package/dist/wu-framework.esm.js.map +1 -1
  8. package/dist/wu-framework.umd.js +1 -1
  9. package/dist/wu-framework.umd.js.map +1 -1
  10. package/package.json +166 -161
  11. package/src/adapters/angular/ai.js +30 -30
  12. package/src/adapters/angular/index.d.ts +154 -154
  13. package/src/adapters/angular/index.js +932 -932
  14. package/src/adapters/angular.d.ts +3 -3
  15. package/src/adapters/angular.js +3 -3
  16. package/src/adapters/index.js +168 -168
  17. package/src/adapters/lit/ai.js +20 -20
  18. package/src/adapters/lit/index.d.ts +120 -120
  19. package/src/adapters/lit/index.js +721 -721
  20. package/src/adapters/lit.d.ts +3 -3
  21. package/src/adapters/lit.js +3 -3
  22. package/src/adapters/preact/ai.js +33 -33
  23. package/src/adapters/preact/index.d.ts +108 -108
  24. package/src/adapters/preact/index.js +661 -661
  25. package/src/adapters/preact.d.ts +3 -3
  26. package/src/adapters/preact.js +3 -3
  27. package/src/adapters/react/index.js +48 -54
  28. package/src/adapters/react.d.ts +3 -3
  29. package/src/adapters/react.js +3 -3
  30. package/src/adapters/shared.js +64 -64
  31. package/src/adapters/solid/ai.js +32 -32
  32. package/src/adapters/solid/index.d.ts +101 -101
  33. package/src/adapters/solid/index.js +586 -586
  34. package/src/adapters/solid.d.ts +3 -3
  35. package/src/adapters/solid.js +3 -3
  36. package/src/adapters/svelte/ai.js +31 -31
  37. package/src/adapters/svelte/index.d.ts +166 -166
  38. package/src/adapters/svelte/index.js +798 -798
  39. package/src/adapters/svelte.d.ts +3 -3
  40. package/src/adapters/svelte.js +3 -3
  41. package/src/adapters/vanilla/ai.js +30 -30
  42. package/src/adapters/vanilla/index.d.ts +179 -179
  43. package/src/adapters/vanilla/index.js +785 -785
  44. package/src/adapters/vanilla.d.ts +3 -3
  45. package/src/adapters/vanilla.js +3 -3
  46. package/src/adapters/vue/ai.js +52 -52
  47. package/src/adapters/vue/index.d.ts +299 -299
  48. package/src/adapters/vue/index.js +610 -610
  49. package/src/adapters/vue.d.ts +3 -3
  50. package/src/adapters/vue.js +3 -3
  51. package/src/ai/wu-ai-actions.js +261 -261
  52. package/src/ai/wu-ai-agent.js +546 -546
  53. package/src/ai/wu-ai-browser-primitives.js +354 -354
  54. package/src/ai/wu-ai-browser.js +380 -380
  55. package/src/ai/wu-ai-context.js +332 -332
  56. package/src/ai/wu-ai-conversation.js +613 -613
  57. package/src/ai/wu-ai-orchestrate.js +1021 -1021
  58. package/src/ai/wu-ai-permissions.js +381 -381
  59. package/src/ai/wu-ai-provider.js +700 -700
  60. package/src/ai/wu-ai-schema.js +225 -225
  61. package/src/ai/wu-ai-triggers.js +396 -396
  62. package/src/ai/wu-ai.js +804 -804
  63. package/src/core/wu-app.js +236 -236
  64. package/src/core/wu-cache.js +498 -477
  65. package/src/core/wu-core.js +1412 -1398
  66. package/src/core/wu-error-boundary.js +396 -382
  67. package/src/core/wu-event-bus.js +390 -348
  68. package/src/core/wu-hooks.js +350 -350
  69. package/src/core/wu-html-parser.js +199 -190
  70. package/src/core/wu-iframe-sandbox.js +328 -328
  71. package/src/core/wu-loader.js +385 -273
  72. package/src/core/wu-logger.js +142 -134
  73. package/src/core/wu-manifest.js +532 -509
  74. package/src/core/wu-mcp-bridge.js +432 -432
  75. package/src/core/wu-overrides.js +510 -510
  76. package/src/core/wu-performance.js +228 -228
  77. package/src/core/wu-plugin.js +401 -348
  78. package/src/core/wu-prefetch.js +414 -414
  79. package/src/core/wu-proxy-sandbox.js +477 -476
  80. package/src/core/wu-sandbox.js +779 -779
  81. package/src/core/wu-script-executor.js +161 -113
  82. package/src/core/wu-snapshot-sandbox.js +227 -227
  83. package/src/core/wu-store.js +13 -3
  84. package/src/core/wu-strategies.js +256 -256
  85. package/src/core/wu-style-bridge.js +477 -477
  86. package/src/index.d.ts +317 -0
  87. package/src/index.js +234 -224
  88. package/src/utils/dependency-resolver.js +327 -327
@@ -1,350 +1,350 @@
1
- /**
2
- * 🪝 WU-HOOKS: LIFECYCLE MIDDLEWARE SYSTEM
3
- *
4
- * Sistema de hooks basado en middleware pattern para control fino:
5
- * - Middleware chain con next()
6
- * - Puede cancelar operaciones (no llamar next)
7
- * - Puede modificar contexto
8
- * - Prioridad de hooks
9
- * - Async/await support
10
- */
11
-
12
- import { logger } from './wu-logger.js';
13
-
14
- export class WuLifecycleHooks {
15
- constructor(core) {
16
- this.core = core;
17
- this.hooks = new Map();
18
- this.executionLog = [];
19
- this.maxLogSize = 100;
20
-
21
- // Lifecycle phases disponibles
22
- this.lifecyclePhases = [
23
- 'beforeInit', // Antes de inicializar framework
24
- 'afterInit', // Después de inicializar
25
- 'beforeLoad', // Antes de cargar una app
26
- 'afterLoad', // Después de cargar
27
- 'beforeMount', // Antes de montar
28
- 'afterMount', // Después de montar
29
- 'beforeUnmount', // Antes de desmontar
30
- 'afterUnmount', // Después de desmontar
31
- 'beforeDestroy', // Antes de destruir framework
32
- 'afterDestroy' // Después de destruir
33
- ];
34
-
35
- // Inicializar hooks
36
- this.lifecyclePhases.forEach(phase => {
37
- this.hooks.set(phase, []);
38
- });
39
-
40
- logger.debug('[WuHooks] 🪝 Lifecycle hooks initialized');
41
- }
42
-
43
- /**
44
- * 📦 USE: Registrar middleware hook
45
- * @param {string} phase - Fase del lifecycle
46
- * @param {Function} middleware - Función middleware (context, next)
47
- * @param {Object} options - { priority, name }
48
- */
49
- use(phase, middleware, options = {}) {
50
- if (!this.hooks.has(phase)) {
51
- throw new Error(`[WuHooks] Unknown lifecycle phase: ${phase}`);
52
- }
53
-
54
- if (typeof middleware !== 'function') {
55
- throw new Error('[WuHooks] Middleware must be a function');
56
- }
57
-
58
- const hook = {
59
- middleware,
60
- name: options.name || `hook_${Date.now()}`,
61
- priority: options.priority || 0,
62
- registeredAt: Date.now()
63
- };
64
-
65
- const hooks = this.hooks.get(phase);
66
- hooks.push(hook);
67
-
68
- // Ordenar por prioridad (mayor primero)
69
- hooks.sort((a, b) => b.priority - a.priority);
70
-
71
- logger.debug(`[WuHooks] Hook "${hook.name}" registered for ${phase} (priority: ${hook.priority})`);
72
-
73
- // Retornar función para desregistrar
74
- return () => this.remove(phase, hook.name);
75
- }
76
-
77
- /**
78
- * 🗑️ REMOVE: Remover hook
79
- * @param {string} phase - Fase del lifecycle
80
- * @param {string} name - Nombre del hook
81
- */
82
- remove(phase, name) {
83
- if (!this.hooks.has(phase)) return;
84
-
85
- const hooks = this.hooks.get(phase);
86
- const index = hooks.findIndex(h => h.name === name);
87
-
88
- if (index > -1) {
89
- hooks.splice(index, 1);
90
- logger.debug(`[WuHooks] Hook "${name}" removed from ${phase}`);
91
- }
92
- }
93
-
94
- /**
95
- * 🎯 EXECUTE: Ejecutar middleware chain
96
- * @param {string} phase - Fase del lifecycle
97
- * @param {Object} context - Contexto a pasar
98
- * @returns {Promise<Object>} Contexto modificado o { cancelled: true }
99
- */
100
- async execute(phase, context = {}) {
101
- const hooks = this.hooks.get(phase);
102
-
103
- if (!hooks || hooks.length === 0) {
104
- return context;
105
- }
106
-
107
- logger.debug(`[WuHooks] Executing ${hooks.length} hooks for ${phase}`);
108
-
109
- // Log para debugging
110
- const executionEntry = {
111
- phase,
112
- timestamp: Date.now(),
113
- hooksCount: hooks.length,
114
- hookNames: hooks.map(h => h.name)
115
- };
116
-
117
- let currentContext = { ...context };
118
- let cancelled = false;
119
-
120
- // Crear cadena de middleware
121
- const executeChain = async (index) => {
122
- // Si llegamos al final de la cadena, retornar contexto
123
- if (index >= hooks.length) {
124
- return currentContext;
125
- }
126
-
127
- const hook = hooks[index];
128
- const startTime = Date.now();
129
-
130
- try {
131
- let nextCalled = false;
132
-
133
- // Función next
134
- const next = async (modifiedContext) => {
135
- nextCalled = true;
136
-
137
- // Si se pasa un contexto modificado, usarlo
138
- if (modifiedContext !== undefined) {
139
- currentContext = { ...currentContext, ...modifiedContext };
140
- }
141
-
142
- // Continuar con siguiente hook
143
- return await executeChain(index + 1);
144
- };
145
-
146
- // Ejecutar middleware
147
- await hook.middleware(currentContext, next);
148
-
149
- // Si no se llamó next(), la operación fue cancelada
150
- if (!nextCalled) {
151
- logger.debug(`[WuHooks] Hook "${hook.name}" cancelled execution`);
152
- cancelled = true;
153
- return { cancelled: true };
154
- }
155
-
156
- const duration = Date.now() - startTime;
157
- logger.debug(`[WuHooks] Hook "${hook.name}" executed in ${duration}ms`);
158
-
159
- } catch (error) {
160
- console.error(`[WuHooks] Error in hook "${hook.name}":`, error);
161
-
162
- // Si hay error, pasar al siguiente hook
163
- return await executeChain(index + 1);
164
- }
165
-
166
- return currentContext;
167
- };
168
-
169
- // Ejecutar cadena
170
- const result = await executeChain(0);
171
-
172
- // Completar log
173
- executionEntry.duration = Date.now() - executionEntry.timestamp;
174
- executionEntry.cancelled = cancelled;
175
- executionEntry.success = !cancelled;
176
-
177
- this.executionLog.push(executionEntry);
178
-
179
- // Mantener límite de log
180
- if (this.executionLog.length > this.maxLogSize) {
181
- this.executionLog.shift();
182
- }
183
-
184
- return result;
185
- }
186
-
187
- /**
188
- * 🚀 HELPER: Registrar hook para múltiples fases
189
- * @param {Array<string>} phases - Fases del lifecycle
190
- * @param {Function} middleware - Función middleware
191
- * @param {Object} options - Opciones
192
- * @returns {Function} Función para desregistrar de todas las fases
193
- */
194
- useMultiple(phases, middleware, options = {}) {
195
- const unregisterFns = phases.map(phase =>
196
- this.use(phase, middleware, { ...options, name: `${options.name}_${phase}` })
197
- );
198
-
199
- // Retornar función que desregistra de todas las fases
200
- return () => unregisterFns.forEach(fn => fn());
201
- }
202
-
203
- /**
204
- * 📋 GET HOOKS: Obtener hooks registrados
205
- * @param {string} phase - Fase del lifecycle (opcional)
206
- * @returns {Object|Array}
207
- */
208
- getHooks(phase) {
209
- if (phase) {
210
- return this.hooks.get(phase) || [];
211
- }
212
-
213
- // Retornar todos los hooks
214
- const allHooks = {};
215
- this.hooks.forEach((hooks, phase) => {
216
- allHooks[phase] = hooks.map(h => ({
217
- name: h.name,
218
- priority: h.priority,
219
- registeredAt: h.registeredAt
220
- }));
221
- });
222
-
223
- return allHooks;
224
- }
225
-
226
- /**
227
- * 📊 GET STATS: Estadísticas de hooks
228
- * @returns {Object}
229
- */
230
- getStats() {
231
- const totalHooks = Array.from(this.hooks.values())
232
- .reduce((sum, hooks) => sum + hooks.length, 0);
233
-
234
- const executionsByPhase = {};
235
- this.executionLog.forEach(entry => {
236
- executionsByPhase[entry.phase] = (executionsByPhase[entry.phase] || 0) + 1;
237
- });
238
-
239
- const avgDuration = this.executionLog.length > 0
240
- ? this.executionLog.reduce((sum, entry) => sum + entry.duration, 0) / this.executionLog.length
241
- : 0;
242
-
243
- const cancelledCount = this.executionLog.filter(entry => entry.cancelled).length;
244
-
245
- return {
246
- totalHooks,
247
- totalExecutions: this.executionLog.length,
248
- executionsByPhase,
249
- avgDuration: Math.round(avgDuration),
250
- cancelledCount,
251
- recentExecutions: this.executionLog.slice(-10)
252
- };
253
- }
254
-
255
- /**
256
- * 🧹 CLEANUP: Limpiar todos los hooks
257
- * @param {string} phase - Fase específica (opcional)
258
- */
259
- cleanup(phase) {
260
- if (phase) {
261
- this.hooks.set(phase, []);
262
- logger.debug(`[WuHooks] Hooks cleaned for ${phase}`);
263
- } else {
264
- this.lifecyclePhases.forEach(p => {
265
- this.hooks.set(p, []);
266
- });
267
- this.executionLog = [];
268
- logger.debug('[WuHooks] 🧹 All hooks cleaned');
269
- }
270
- }
271
- }
272
-
273
- /**
274
- * 🔧 HELPER: Crear middleware hooks fácilmente
275
- */
276
-
277
- /**
278
- * Crear hook simple que siempre llama next
279
- * @param {Function} fn - Función a ejecutar
280
- * @returns {Function} Middleware function
281
- */
282
- export const createSimpleHook = (fn) => {
283
- return async (context, next) => {
284
- await fn(context);
285
- await next();
286
- };
287
- };
288
-
289
- /**
290
- * Crear hook condicional
291
- * @param {Function} condition - Función de condición (context) => boolean
292
- * @param {Function} fn - Función a ejecutar si condición es true
293
- * @returns {Function} Middleware function
294
- */
295
- export const createConditionalHook = (condition, fn) => {
296
- return async (context, next) => {
297
- if (await condition(context)) {
298
- await fn(context);
299
- }
300
- await next();
301
- };
302
- };
303
-
304
- /**
305
- * Crear hook que puede cancelar operación
306
- * @param {Function} shouldContinue - Función que retorna true para continuar
307
- * @returns {Function} Middleware function
308
- */
309
- export const createGuardHook = (shouldContinue) => {
310
- return async (context, next) => {
311
- if (await shouldContinue(context)) {
312
- await next();
313
- }
314
- // Si no retorna true, no llama next() y cancela
315
- };
316
- };
317
-
318
- /**
319
- * Crear hook que modifica contexto
320
- * @param {Function} transformer - Función que transforma el contexto
321
- * @returns {Function} Middleware function
322
- */
323
- export const createTransformHook = (transformer) => {
324
- return async (context, next) => {
325
- const modified = await transformer(context);
326
- await next(modified);
327
- };
328
- };
329
-
330
- /**
331
- * Crear hook con timeout
332
- * @param {Function} fn - Función a ejecutar
333
- * @param {number} timeout - Timeout en ms
334
- * @returns {Function} Middleware function
335
- */
336
- export const createTimedHook = (fn, timeout = 5000) => {
337
- return async (context, next) => {
338
- const timeoutPromise = new Promise((_, reject) =>
339
- setTimeout(() => reject(new Error('Hook timeout')), timeout)
340
- );
341
-
342
- try {
343
- await Promise.race([fn(context), timeoutPromise]);
344
- await next();
345
- } catch (error) {
346
- console.error('[WuHooks] Timed hook failed:', error);
347
- await next(); // Continuar a pesar del error
348
- }
349
- };
350
- };
1
+ /**
2
+ * 🪝 WU-HOOKS: LIFECYCLE MIDDLEWARE SYSTEM
3
+ *
4
+ * Sistema de hooks basado en middleware pattern para control fino:
5
+ * - Middleware chain con next()
6
+ * - Puede cancelar operaciones (no llamar next)
7
+ * - Puede modificar contexto
8
+ * - Prioridad de hooks
9
+ * - Async/await support
10
+ */
11
+
12
+ import { logger } from './wu-logger.js';
13
+
14
+ export class WuLifecycleHooks {
15
+ constructor(core) {
16
+ this.core = core;
17
+ this.hooks = new Map();
18
+ this.executionLog = [];
19
+ this.maxLogSize = 100;
20
+
21
+ // Lifecycle phases disponibles
22
+ this.lifecyclePhases = [
23
+ 'beforeInit', // Antes de inicializar framework
24
+ 'afterInit', // Después de inicializar
25
+ 'beforeLoad', // Antes de cargar una app
26
+ 'afterLoad', // Después de cargar
27
+ 'beforeMount', // Antes de montar
28
+ 'afterMount', // Después de montar
29
+ 'beforeUnmount', // Antes de desmontar
30
+ 'afterUnmount', // Después de desmontar
31
+ 'beforeDestroy', // Antes de destruir framework
32
+ 'afterDestroy' // Después de destruir
33
+ ];
34
+
35
+ // Inicializar hooks
36
+ this.lifecyclePhases.forEach(phase => {
37
+ this.hooks.set(phase, []);
38
+ });
39
+
40
+ logger.debug('[WuHooks] 🪝 Lifecycle hooks initialized');
41
+ }
42
+
43
+ /**
44
+ * 📦 USE: Registrar middleware hook
45
+ * @param {string} phase - Fase del lifecycle
46
+ * @param {Function} middleware - Función middleware (context, next)
47
+ * @param {Object} options - { priority, name }
48
+ */
49
+ use(phase, middleware, options = {}) {
50
+ if (!this.hooks.has(phase)) {
51
+ throw new Error(`[WuHooks] Unknown lifecycle phase: ${phase}`);
52
+ }
53
+
54
+ if (typeof middleware !== 'function') {
55
+ throw new Error('[WuHooks] Middleware must be a function');
56
+ }
57
+
58
+ const hook = {
59
+ middleware,
60
+ name: options.name || `hook_${Date.now()}`,
61
+ priority: options.priority || 0,
62
+ registeredAt: Date.now()
63
+ };
64
+
65
+ const hooks = this.hooks.get(phase);
66
+ hooks.push(hook);
67
+
68
+ // Ordenar por prioridad (mayor primero)
69
+ hooks.sort((a, b) => b.priority - a.priority);
70
+
71
+ logger.debug(`[WuHooks] Hook "${hook.name}" registered for ${phase} (priority: ${hook.priority})`);
72
+
73
+ // Retornar función para desregistrar
74
+ return () => this.remove(phase, hook.name);
75
+ }
76
+
77
+ /**
78
+ * 🗑️ REMOVE: Remover hook
79
+ * @param {string} phase - Fase del lifecycle
80
+ * @param {string} name - Nombre del hook
81
+ */
82
+ remove(phase, name) {
83
+ if (!this.hooks.has(phase)) return;
84
+
85
+ const hooks = this.hooks.get(phase);
86
+ const index = hooks.findIndex(h => h.name === name);
87
+
88
+ if (index > -1) {
89
+ hooks.splice(index, 1);
90
+ logger.debug(`[WuHooks] Hook "${name}" removed from ${phase}`);
91
+ }
92
+ }
93
+
94
+ /**
95
+ * 🎯 EXECUTE: Ejecutar middleware chain
96
+ * @param {string} phase - Fase del lifecycle
97
+ * @param {Object} context - Contexto a pasar
98
+ * @returns {Promise<Object>} Contexto modificado o { cancelled: true }
99
+ */
100
+ async execute(phase, context = {}) {
101
+ const hooks = this.hooks.get(phase);
102
+
103
+ if (!hooks || hooks.length === 0) {
104
+ return context;
105
+ }
106
+
107
+ logger.debug(`[WuHooks] Executing ${hooks.length} hooks for ${phase}`);
108
+
109
+ // Log para debugging
110
+ const executionEntry = {
111
+ phase,
112
+ timestamp: Date.now(),
113
+ hooksCount: hooks.length,
114
+ hookNames: hooks.map(h => h.name)
115
+ };
116
+
117
+ let currentContext = { ...context };
118
+ let cancelled = false;
119
+
120
+ // Crear cadena de middleware
121
+ const executeChain = async (index) => {
122
+ // Si llegamos al final de la cadena, retornar contexto
123
+ if (index >= hooks.length) {
124
+ return currentContext;
125
+ }
126
+
127
+ const hook = hooks[index];
128
+ const startTime = Date.now();
129
+
130
+ try {
131
+ let nextCalled = false;
132
+
133
+ // Función next
134
+ const next = async (modifiedContext) => {
135
+ nextCalled = true;
136
+
137
+ // Si se pasa un contexto modificado, usarlo
138
+ if (modifiedContext !== undefined) {
139
+ currentContext = { ...currentContext, ...modifiedContext };
140
+ }
141
+
142
+ // Continuar con siguiente hook
143
+ return await executeChain(index + 1);
144
+ };
145
+
146
+ // Ejecutar middleware
147
+ await hook.middleware(currentContext, next);
148
+
149
+ // Si no se llamó next(), la operación fue cancelada
150
+ if (!nextCalled) {
151
+ logger.debug(`[WuHooks] Hook "${hook.name}" cancelled execution`);
152
+ cancelled = true;
153
+ return { cancelled: true };
154
+ }
155
+
156
+ const duration = Date.now() - startTime;
157
+ logger.debug(`[WuHooks] Hook "${hook.name}" executed in ${duration}ms`);
158
+
159
+ } catch (error) {
160
+ console.error(`[WuHooks] Error in hook "${hook.name}":`, error);
161
+
162
+ // Si hay error, pasar al siguiente hook
163
+ return await executeChain(index + 1);
164
+ }
165
+
166
+ return currentContext;
167
+ };
168
+
169
+ // Ejecutar cadena
170
+ const result = await executeChain(0);
171
+
172
+ // Completar log
173
+ executionEntry.duration = Date.now() - executionEntry.timestamp;
174
+ executionEntry.cancelled = cancelled;
175
+ executionEntry.success = !cancelled;
176
+
177
+ this.executionLog.push(executionEntry);
178
+
179
+ // Mantener límite de log
180
+ if (this.executionLog.length > this.maxLogSize) {
181
+ this.executionLog.shift();
182
+ }
183
+
184
+ return result;
185
+ }
186
+
187
+ /**
188
+ * 🚀 HELPER: Registrar hook para múltiples fases
189
+ * @param {Array<string>} phases - Fases del lifecycle
190
+ * @param {Function} middleware - Función middleware
191
+ * @param {Object} options - Opciones
192
+ * @returns {Function} Función para desregistrar de todas las fases
193
+ */
194
+ useMultiple(phases, middleware, options = {}) {
195
+ const unregisterFns = phases.map(phase =>
196
+ this.use(phase, middleware, { ...options, name: `${options.name}_${phase}` })
197
+ );
198
+
199
+ // Retornar función que desregistra de todas las fases
200
+ return () => unregisterFns.forEach(fn => fn());
201
+ }
202
+
203
+ /**
204
+ * 📋 GET HOOKS: Obtener hooks registrados
205
+ * @param {string} phase - Fase del lifecycle (opcional)
206
+ * @returns {Object|Array}
207
+ */
208
+ getHooks(phase) {
209
+ if (phase) {
210
+ return this.hooks.get(phase) || [];
211
+ }
212
+
213
+ // Retornar todos los hooks
214
+ const allHooks = {};
215
+ this.hooks.forEach((hooks, phase) => {
216
+ allHooks[phase] = hooks.map(h => ({
217
+ name: h.name,
218
+ priority: h.priority,
219
+ registeredAt: h.registeredAt
220
+ }));
221
+ });
222
+
223
+ return allHooks;
224
+ }
225
+
226
+ /**
227
+ * 📊 GET STATS: Estadísticas de hooks
228
+ * @returns {Object}
229
+ */
230
+ getStats() {
231
+ const totalHooks = Array.from(this.hooks.values())
232
+ .reduce((sum, hooks) => sum + hooks.length, 0);
233
+
234
+ const executionsByPhase = {};
235
+ this.executionLog.forEach(entry => {
236
+ executionsByPhase[entry.phase] = (executionsByPhase[entry.phase] || 0) + 1;
237
+ });
238
+
239
+ const avgDuration = this.executionLog.length > 0
240
+ ? this.executionLog.reduce((sum, entry) => sum + entry.duration, 0) / this.executionLog.length
241
+ : 0;
242
+
243
+ const cancelledCount = this.executionLog.filter(entry => entry.cancelled).length;
244
+
245
+ return {
246
+ totalHooks,
247
+ totalExecutions: this.executionLog.length,
248
+ executionsByPhase,
249
+ avgDuration: Math.round(avgDuration),
250
+ cancelledCount,
251
+ recentExecutions: this.executionLog.slice(-10)
252
+ };
253
+ }
254
+
255
+ /**
256
+ * 🧹 CLEANUP: Limpiar todos los hooks
257
+ * @param {string} phase - Fase específica (opcional)
258
+ */
259
+ cleanup(phase) {
260
+ if (phase) {
261
+ this.hooks.set(phase, []);
262
+ logger.debug(`[WuHooks] Hooks cleaned for ${phase}`);
263
+ } else {
264
+ this.lifecyclePhases.forEach(p => {
265
+ this.hooks.set(p, []);
266
+ });
267
+ this.executionLog = [];
268
+ logger.debug('[WuHooks] 🧹 All hooks cleaned');
269
+ }
270
+ }
271
+ }
272
+
273
+ /**
274
+ * 🔧 HELPER: Crear middleware hooks fácilmente
275
+ */
276
+
277
+ /**
278
+ * Crear hook simple que siempre llama next
279
+ * @param {Function} fn - Función a ejecutar
280
+ * @returns {Function} Middleware function
281
+ */
282
+ export const createSimpleHook = (fn) => {
283
+ return async (context, next) => {
284
+ await fn(context);
285
+ await next();
286
+ };
287
+ };
288
+
289
+ /**
290
+ * Crear hook condicional
291
+ * @param {Function} condition - Función de condición (context) => boolean
292
+ * @param {Function} fn - Función a ejecutar si condición es true
293
+ * @returns {Function} Middleware function
294
+ */
295
+ export const createConditionalHook = (condition, fn) => {
296
+ return async (context, next) => {
297
+ if (await condition(context)) {
298
+ await fn(context);
299
+ }
300
+ await next();
301
+ };
302
+ };
303
+
304
+ /**
305
+ * Crear hook que puede cancelar operación
306
+ * @param {Function} shouldContinue - Función que retorna true para continuar
307
+ * @returns {Function} Middleware function
308
+ */
309
+ export const createGuardHook = (shouldContinue) => {
310
+ return async (context, next) => {
311
+ if (await shouldContinue(context)) {
312
+ await next();
313
+ }
314
+ // Si no retorna true, no llama next() y cancela
315
+ };
316
+ };
317
+
318
+ /**
319
+ * Crear hook que modifica contexto
320
+ * @param {Function} transformer - Función que transforma el contexto
321
+ * @returns {Function} Middleware function
322
+ */
323
+ export const createTransformHook = (transformer) => {
324
+ return async (context, next) => {
325
+ const modified = await transformer(context);
326
+ await next(modified);
327
+ };
328
+ };
329
+
330
+ /**
331
+ * Crear hook con timeout
332
+ * @param {Function} fn - Función a ejecutar
333
+ * @param {number} timeout - Timeout en ms
334
+ * @returns {Function} Middleware function
335
+ */
336
+ export const createTimedHook = (fn, timeout = 5000) => {
337
+ return async (context, next) => {
338
+ const timeoutPromise = new Promise((_, reject) =>
339
+ setTimeout(() => reject(new Error('Hook timeout')), timeout)
340
+ );
341
+
342
+ try {
343
+ await Promise.race([fn(context), timeoutPromise]);
344
+ await next();
345
+ } catch (error) {
346
+ console.error('[WuHooks] Timed hook failed:', error);
347
+ await next(); // Continuar a pesar del error
348
+ }
349
+ };
350
+ };