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.
- package/README.md +52 -20
- package/dist/wu-framework.cjs.js +1 -1
- package/dist/wu-framework.cjs.js.map +1 -1
- package/dist/wu-framework.dev.js +15511 -15146
- package/dist/wu-framework.dev.js.map +1 -1
- package/dist/wu-framework.esm.js +1 -1
- package/dist/wu-framework.esm.js.map +1 -1
- package/dist/wu-framework.umd.js +1 -1
- package/dist/wu-framework.umd.js.map +1 -1
- package/package.json +166 -161
- package/src/adapters/angular/ai.js +30 -30
- package/src/adapters/angular/index.d.ts +154 -154
- package/src/adapters/angular/index.js +932 -932
- package/src/adapters/angular.d.ts +3 -3
- package/src/adapters/angular.js +3 -3
- package/src/adapters/index.js +168 -168
- package/src/adapters/lit/ai.js +20 -20
- package/src/adapters/lit/index.d.ts +120 -120
- package/src/adapters/lit/index.js +721 -721
- package/src/adapters/lit.d.ts +3 -3
- package/src/adapters/lit.js +3 -3
- package/src/adapters/preact/ai.js +33 -33
- package/src/adapters/preact/index.d.ts +108 -108
- package/src/adapters/preact/index.js +661 -661
- package/src/adapters/preact.d.ts +3 -3
- package/src/adapters/preact.js +3 -3
- package/src/adapters/react/index.js +48 -54
- package/src/adapters/react.d.ts +3 -3
- package/src/adapters/react.js +3 -3
- package/src/adapters/shared.js +64 -64
- package/src/adapters/solid/ai.js +32 -32
- package/src/adapters/solid/index.d.ts +101 -101
- package/src/adapters/solid/index.js +586 -586
- package/src/adapters/solid.d.ts +3 -3
- package/src/adapters/solid.js +3 -3
- package/src/adapters/svelte/ai.js +31 -31
- package/src/adapters/svelte/index.d.ts +166 -166
- package/src/adapters/svelte/index.js +798 -798
- package/src/adapters/svelte.d.ts +3 -3
- package/src/adapters/svelte.js +3 -3
- package/src/adapters/vanilla/ai.js +30 -30
- package/src/adapters/vanilla/index.d.ts +179 -179
- package/src/adapters/vanilla/index.js +785 -785
- package/src/adapters/vanilla.d.ts +3 -3
- package/src/adapters/vanilla.js +3 -3
- package/src/adapters/vue/ai.js +52 -52
- package/src/adapters/vue/index.d.ts +299 -299
- package/src/adapters/vue/index.js +610 -610
- package/src/adapters/vue.d.ts +3 -3
- package/src/adapters/vue.js +3 -3
- package/src/ai/wu-ai-actions.js +261 -261
- package/src/ai/wu-ai-agent.js +546 -546
- package/src/ai/wu-ai-browser-primitives.js +354 -354
- package/src/ai/wu-ai-browser.js +380 -380
- package/src/ai/wu-ai-context.js +332 -332
- package/src/ai/wu-ai-conversation.js +613 -613
- package/src/ai/wu-ai-orchestrate.js +1021 -1021
- package/src/ai/wu-ai-permissions.js +381 -381
- package/src/ai/wu-ai-provider.js +700 -700
- package/src/ai/wu-ai-schema.js +225 -225
- package/src/ai/wu-ai-triggers.js +396 -396
- package/src/ai/wu-ai.js +804 -804
- package/src/core/wu-app.js +236 -236
- package/src/core/wu-cache.js +498 -477
- package/src/core/wu-core.js +1412 -1398
- package/src/core/wu-error-boundary.js +396 -382
- package/src/core/wu-event-bus.js +390 -348
- package/src/core/wu-hooks.js +350 -350
- package/src/core/wu-html-parser.js +199 -190
- package/src/core/wu-iframe-sandbox.js +328 -328
- package/src/core/wu-loader.js +385 -273
- package/src/core/wu-logger.js +142 -134
- package/src/core/wu-manifest.js +532 -509
- package/src/core/wu-mcp-bridge.js +432 -432
- package/src/core/wu-overrides.js +510 -510
- package/src/core/wu-performance.js +228 -228
- package/src/core/wu-plugin.js +401 -348
- package/src/core/wu-prefetch.js +414 -414
- package/src/core/wu-proxy-sandbox.js +477 -476
- package/src/core/wu-sandbox.js +779 -779
- package/src/core/wu-script-executor.js +161 -113
- package/src/core/wu-snapshot-sandbox.js +227 -227
- package/src/core/wu-store.js +13 -3
- package/src/core/wu-strategies.js +256 -256
- package/src/core/wu-style-bridge.js +477 -477
- package/src/index.d.ts +317 -0
- package/src/index.js +234 -224
- package/src/utils/dependency-resolver.js +327 -327
package/src/core/wu-event-bus.js
CHANGED
|
@@ -1,348 +1,390 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ๐ก WU-EVENT-BUS: SECURE PUB/SUB SYSTEM
|
|
3
|
-
*
|
|
4
|
-
* Sistema de eventos para comunicaciรณn entre microfrontends
|
|
5
|
-
* - Pub/Sub pattern con validaciรณn de origen
|
|
6
|
-
* - Event namespaces
|
|
7
|
-
* - Wildcards
|
|
8
|
-
* - Event replay
|
|
9
|
-
* - Verificaciรณn de apps autorizadas
|
|
10
|
-
*/
|
|
11
|
-
import { logger } from './wu-logger.js';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
*
|
|
68
|
-
* @
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* ๐
|
|
125
|
-
*/
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (this.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
*
|
|
247
|
-
*/
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
.
|
|
252
|
-
.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
*
|
|
289
|
-
*/
|
|
290
|
-
|
|
291
|
-
if (!
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
this.
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
1
|
+
/**
|
|
2
|
+
* ๐ก WU-EVENT-BUS: SECURE PUB/SUB SYSTEM
|
|
3
|
+
*
|
|
4
|
+
* Sistema de eventos para comunicaciรณn entre microfrontends
|
|
5
|
+
* - Pub/Sub pattern con validaciรณn de origen
|
|
6
|
+
* - Event namespaces
|
|
7
|
+
* - Wildcards
|
|
8
|
+
* - Event replay
|
|
9
|
+
* - Verificaciรณn de apps autorizadas
|
|
10
|
+
*/
|
|
11
|
+
import { logger } from './wu-logger.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {Object} WuEvent
|
|
15
|
+
* @property {string} name - Event name
|
|
16
|
+
* @property {*} data - Event payload
|
|
17
|
+
* @property {number} timestamp - Event timestamp
|
|
18
|
+
* @property {string} appName - Source app name
|
|
19
|
+
* @property {Object} meta - Additional metadata
|
|
20
|
+
* @property {boolean} verified - Whether origin was verified
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @typedef {Object} WuEventBusConfig
|
|
25
|
+
* @property {number} [maxHistory=100] - Maximum events in history
|
|
26
|
+
* @property {boolean} [enableReplay=true] - Enable event replay
|
|
27
|
+
* @property {boolean} [enableWildcards=true] - Enable wildcard matching
|
|
28
|
+
* @property {boolean} [logEvents=false] - Log all events
|
|
29
|
+
* @property {boolean} [strictMode=false] - Reject unauthorized events
|
|
30
|
+
* @property {boolean} [validateOrigin=true] - Validate event origins
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
export class WuEventBus {
|
|
34
|
+
constructor() {
|
|
35
|
+
this.listeners = new Map();
|
|
36
|
+
this.history = [];
|
|
37
|
+
|
|
38
|
+
// ๐ SEGURIDAD: Registro de apps autorizadas con tokens
|
|
39
|
+
this.authorizedApps = new Map(); // appName -> { token, permissions }
|
|
40
|
+
this.trustedEvents = new Set(['wu:*', 'system:*']); // Eventos del sistema
|
|
41
|
+
|
|
42
|
+
// Auto-detect production environment for strictMode default
|
|
43
|
+
const isProduction = typeof process !== 'undefined' && process.env?.NODE_ENV === 'production';
|
|
44
|
+
|
|
45
|
+
this.config = {
|
|
46
|
+
maxHistory: 100,
|
|
47
|
+
enableReplay: true,
|
|
48
|
+
enableWildcards: true,
|
|
49
|
+
logEvents: false,
|
|
50
|
+
// ๐ Opciones de seguridad
|
|
51
|
+
strictMode: isProduction, // Auto-enabled in production, permissive in development
|
|
52
|
+
validateOrigin: true // Valida que appName sea una app registrada
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
this._permissiveWarned = false;
|
|
56
|
+
|
|
57
|
+
this.stats = {
|
|
58
|
+
emitted: 0,
|
|
59
|
+
subscriptions: 0,
|
|
60
|
+
rejected: 0 // Eventos rechazados por seguridad
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* ๐ REGISTER APP: Registrar app autorizada para emitir eventos
|
|
66
|
+
* @param {string} appName - Nombre de la app
|
|
67
|
+
* @param {Object} options - { permissions: ['event:*'], token }
|
|
68
|
+
* @returns {string} Token de autorizaciรณn
|
|
69
|
+
*/
|
|
70
|
+
registerApp(appName, options = {}) {
|
|
71
|
+
const token = options.token || this._generateToken();
|
|
72
|
+
|
|
73
|
+
this.authorizedApps.set(appName, {
|
|
74
|
+
token,
|
|
75
|
+
permissions: options.permissions || ['*'], // Por defecto puede emitir todo
|
|
76
|
+
registeredAt: Date.now()
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return token;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* ๐ UNREGISTER APP: Desregistrar app
|
|
84
|
+
* @param {string} appName
|
|
85
|
+
*/
|
|
86
|
+
unregisterApp(appName) {
|
|
87
|
+
this.authorizedApps.delete(appName);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* ๐ VALIDATE ORIGIN: Verificar que el emisor estรก autorizado
|
|
92
|
+
* @param {string} eventName
|
|
93
|
+
* @param {string} appName
|
|
94
|
+
* @param {string} token
|
|
95
|
+
* @returns {boolean}
|
|
96
|
+
*/
|
|
97
|
+
_validateOrigin(eventName, appName, token) {
|
|
98
|
+
// Eventos del sistema siempre permitidos
|
|
99
|
+
if (this._isSystemEvent(eventName)) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Si no estรก en modo estricto, permitir todo
|
|
104
|
+
if (!this.config.strictMode) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Verificar que la app estรฉ registrada
|
|
109
|
+
const appInfo = this.authorizedApps.get(appName);
|
|
110
|
+
if (!appInfo) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Verificar token si se proporciona
|
|
115
|
+
if (token && appInfo.token !== token) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Verificar permisos
|
|
120
|
+
return this._hasPermission(appInfo.permissions, eventName);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* ๐ HAS PERMISSION: Verificar si la app tiene permiso para el evento
|
|
125
|
+
*/
|
|
126
|
+
_hasPermission(permissions, eventName) {
|
|
127
|
+
if (permissions.includes('*')) return true;
|
|
128
|
+
|
|
129
|
+
return permissions.some(pattern => {
|
|
130
|
+
if (pattern === eventName) return true;
|
|
131
|
+
if (pattern.includes('*')) {
|
|
132
|
+
return this.matchesWildcard(eventName, pattern);
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* ๐ IS SYSTEM EVENT: Verificar si es un evento del sistema
|
|
140
|
+
*/
|
|
141
|
+
_isSystemEvent(eventName) {
|
|
142
|
+
return eventName.startsWith('wu:') ||
|
|
143
|
+
eventName.startsWith('system:') ||
|
|
144
|
+
eventName.startsWith('app:');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* ๐ GENERATE TOKEN: Generar token รบnico
|
|
149
|
+
*/
|
|
150
|
+
_generateToken() {
|
|
151
|
+
return `wu_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* WARN PERMISSIVE MODE: Log a one-time warning when strictMode is off
|
|
156
|
+
* Alerts developers that events are flowing without authorization checks
|
|
157
|
+
*/
|
|
158
|
+
_warnPermissiveMode() {
|
|
159
|
+
if (this._permissiveWarned) return;
|
|
160
|
+
this._permissiveWarned = true;
|
|
161
|
+
logger.warn(
|
|
162
|
+
'[WuEventBus] strictMode is disabled. Events are emitted without authorization checks. ' +
|
|
163
|
+
'Enable strictMode for production by calling enableStrictMode() or setting NODE_ENV=production.'
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* ๐ข EMIT: Emitir evento con validaciรณn de origen
|
|
169
|
+
* @param {string} eventName - Nombre del evento
|
|
170
|
+
* @param {*} data - Datos del evento
|
|
171
|
+
* @param {Object} options - { appName, timestamp, meta, token }
|
|
172
|
+
*/
|
|
173
|
+
emit(eventName, data, options = {}) {
|
|
174
|
+
const appName = options.appName || 'unknown';
|
|
175
|
+
|
|
176
|
+
// Warn once if running in permissive mode (strictMode off)
|
|
177
|
+
if (!this.config.strictMode) {
|
|
178
|
+
this._warnPermissiveMode();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ๐ Validar origen si estรก habilitado
|
|
182
|
+
if (this.config.validateOrigin && this.config.strictMode) {
|
|
183
|
+
if (!this._validateOrigin(eventName, appName, options.token)) {
|
|
184
|
+
this.stats.rejected++;
|
|
185
|
+
logger.warn(`[WuEventBus] ๐ซ Event rejected: ${eventName} from ${appName} (unauthorized)`);
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const event = {
|
|
191
|
+
name: eventName,
|
|
192
|
+
data,
|
|
193
|
+
timestamp: options.timestamp || Date.now(),
|
|
194
|
+
appName,
|
|
195
|
+
meta: options.meta || {},
|
|
196
|
+
// ๐ Marcar si el origen fue verificado
|
|
197
|
+
verified: this.authorizedApps.has(appName)
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// Agregar a historial
|
|
201
|
+
if (this.config.enableReplay) {
|
|
202
|
+
this.addToHistory(event);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Log si estรก habilitado
|
|
206
|
+
if (this.config.logEvents) {
|
|
207
|
+
logger.debug(`[WuEventBus] ๐ข ${eventName}`, data);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Notificar listeners exactos
|
|
211
|
+
const exactListeners = this.listeners.get(eventName);
|
|
212
|
+
if (exactListeners) {
|
|
213
|
+
exactListeners.forEach(callback => {
|
|
214
|
+
try {
|
|
215
|
+
callback(event);
|
|
216
|
+
} catch (error) {
|
|
217
|
+
console.error(`[WuEventBus] โ Error in listener for ${eventName}:`, error);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Notificar listeners con wildcards
|
|
223
|
+
if (this.config.enableWildcards) {
|
|
224
|
+
this.notifyWildcardListeners(eventName, event);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
this.stats.emitted++;
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* ๐ ON: Suscribirse a evento
|
|
233
|
+
*/
|
|
234
|
+
on(eventName, callback) {
|
|
235
|
+
if (!this.listeners.has(eventName)) {
|
|
236
|
+
this.listeners.set(eventName, new Set());
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
this.listeners.get(eventName).add(callback);
|
|
240
|
+
this.stats.subscriptions++;
|
|
241
|
+
|
|
242
|
+
return () => this.off(eventName, callback);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* ๐ OFF: Desuscribirse de evento
|
|
247
|
+
*/
|
|
248
|
+
off(eventName, callback) {
|
|
249
|
+
const listeners = this.listeners.get(eventName);
|
|
250
|
+
if (listeners) {
|
|
251
|
+
listeners.delete(callback);
|
|
252
|
+
if (listeners.size === 0) {
|
|
253
|
+
this.listeners.delete(eventName);
|
|
254
|
+
}
|
|
255
|
+
this.stats.subscriptions--;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* ๐ฏ ONCE: Suscribirse una sola vez
|
|
261
|
+
*/
|
|
262
|
+
once(eventName, callback) {
|
|
263
|
+
const wrappedCallback = (event) => {
|
|
264
|
+
callback(event);
|
|
265
|
+
this.off(eventName, wrappedCallback);
|
|
266
|
+
};
|
|
267
|
+
return this.on(eventName, wrappedCallback);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* ๐ WILDCARD LISTENERS
|
|
272
|
+
*/
|
|
273
|
+
notifyWildcardListeners(eventName, event) {
|
|
274
|
+
for (const [pattern, listeners] of this.listeners) {
|
|
275
|
+
if (this.matchesWildcard(eventName, pattern)) {
|
|
276
|
+
listeners.forEach(callback => {
|
|
277
|
+
try {
|
|
278
|
+
callback(event);
|
|
279
|
+
} catch (error) {
|
|
280
|
+
console.error(`[WuEventBus] โ Error in wildcard listener for ${pattern}:`, error);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* ๐ฏ MATCHES WILDCARD
|
|
289
|
+
*/
|
|
290
|
+
matchesWildcard(eventName, pattern) {
|
|
291
|
+
if (!pattern.includes('*')) return false;
|
|
292
|
+
const regexPattern = pattern
|
|
293
|
+
.replace(/\./g, '\\.')
|
|
294
|
+
.replace(/\*/g, '.*');
|
|
295
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
296
|
+
return regex.test(eventName);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* ๐ ADD TO HISTORY
|
|
301
|
+
*/
|
|
302
|
+
addToHistory(event) {
|
|
303
|
+
this.history.push(event);
|
|
304
|
+
if (this.history.length > this.config.maxHistory) {
|
|
305
|
+
this.history.shift();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* ๐ REPLAY
|
|
311
|
+
*/
|
|
312
|
+
replay(eventNameOrPattern, callback) {
|
|
313
|
+
const events = this.history.filter(event => {
|
|
314
|
+
if (eventNameOrPattern.includes('*')) {
|
|
315
|
+
return this.matchesWildcard(event.name, eventNameOrPattern);
|
|
316
|
+
}
|
|
317
|
+
return event.name === eventNameOrPattern;
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
events.forEach(event => {
|
|
321
|
+
try {
|
|
322
|
+
callback(event);
|
|
323
|
+
} catch (error) {
|
|
324
|
+
console.error(`[WuEventBus] โ Error replaying event:`, error);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* ๐งน CLEAR HISTORY
|
|
331
|
+
*/
|
|
332
|
+
clearHistory(eventNameOrPattern) {
|
|
333
|
+
if (!eventNameOrPattern) {
|
|
334
|
+
this.history = [];
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
this.history = this.history.filter(event => {
|
|
339
|
+
if (eventNameOrPattern.includes('*')) {
|
|
340
|
+
return !this.matchesWildcard(event.name, eventNameOrPattern);
|
|
341
|
+
}
|
|
342
|
+
return event.name !== eventNameOrPattern;
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* ๐ GET STATS
|
|
348
|
+
*/
|
|
349
|
+
getStats() {
|
|
350
|
+
return {
|
|
351
|
+
...this.stats,
|
|
352
|
+
activeListeners: this.listeners.size,
|
|
353
|
+
historySize: this.history.length,
|
|
354
|
+
authorizedApps: this.authorizedApps.size,
|
|
355
|
+
listenersByEvent: Array.from(this.listeners.entries()).map(([event, listeners]) => ({
|
|
356
|
+
event,
|
|
357
|
+
listeners: listeners.size
|
|
358
|
+
}))
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* โ๏ธ CONFIGURE
|
|
364
|
+
*/
|
|
365
|
+
configure(config) {
|
|
366
|
+
this.config = { ...this.config, ...config };
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* ๐ ENABLE STRICT MODE: Activar modo estricto de seguridad
|
|
371
|
+
*/
|
|
372
|
+
enableStrictMode() {
|
|
373
|
+
this.config.strictMode = true;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* ๐ DISABLE STRICT MODE
|
|
378
|
+
*/
|
|
379
|
+
disableStrictMode() {
|
|
380
|
+
this.config.strictMode = false;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* ๐๏ธ REMOVE ALL
|
|
385
|
+
*/
|
|
386
|
+
removeAll() {
|
|
387
|
+
this.listeners.clear();
|
|
388
|
+
this.stats.subscriptions = 0;
|
|
389
|
+
}
|
|
390
|
+
}
|