fastevent 2.5.0 → 2.5.1
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/dist/executors/index.js +1 -1
- package/dist/executors/index.js.map +1 -1
- package/dist/executors/index.mjs +1 -1
- package/dist/executors/index.mjs.map +1 -1
- package/dist/index.d.mts +81 -54
- package/dist/index.d.ts +81 -54
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/pipes/index.d.mts +4 -4
- package/dist/pipes/index.d.ts +4 -4
- package/dist/pipes/index.js +1 -1
- package/dist/pipes/index.js.map +1 -1
- package/dist/pipes/index.mjs +1 -1
- package/dist/pipes/index.mjs.map +1 -1
- package/dist/viewer/index.js +104 -104
- package/dist/viewer/index.js.map +1 -1
- package/dist/viewer/index.mjs +393 -1089
- package/dist/viewer/index.mjs.map +1 -1
- package/package.json +1 -1
- package/readme.md +66 -65
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -55,7 +55,7 @@ events.onAny((message) => {
|
|
|
55
55
|
Listener functions receive a `Message` object that contains the following properties:
|
|
56
56
|
|
|
57
57
|
```ts
|
|
58
|
-
events.on(
|
|
58
|
+
events.on("user/login", (message) => {
|
|
59
59
|
// {
|
|
60
60
|
// type: 'user/login', // Event name
|
|
61
61
|
// payload: { id: 1 }, // Event data
|
|
@@ -72,13 +72,13 @@ Retain the last event data, so subsequent subscribers can immediately receive th
|
|
|
72
72
|
const events = new FastEvent();
|
|
73
73
|
|
|
74
74
|
// Publish and retain event
|
|
75
|
-
events.emit(
|
|
75
|
+
events.emit("config/theme", { dark: true }, true);
|
|
76
76
|
// Equivalent to
|
|
77
|
-
events.emit(
|
|
77
|
+
events.emit("config/theme", { dark: true }, { retain: true });
|
|
78
78
|
|
|
79
79
|
// Subsequent subscribers immediately receive the retained value
|
|
80
|
-
events.on(
|
|
81
|
-
console.log(
|
|
80
|
+
events.on("config/theme", (message) => {
|
|
81
|
+
console.log("Theme:", message.payload); // Immediately outputs: { dark: true }
|
|
82
82
|
});
|
|
83
83
|
```
|
|
84
84
|
|
|
@@ -86,25 +86,25 @@ events.on('config/theme', (message) => {
|
|
|
86
86
|
|
|
87
87
|
`FastEvent` supports hierarchical event publishing and subscription.
|
|
88
88
|
|
|
89
|
-
-
|
|
90
|
-
-
|
|
89
|
+
- The default event hierarchy delimiter is `/`, which can be modified via `options.delimiter`
|
|
90
|
+
- Two types of wildcards are supported when subscribing to events: `*` matches a single path level, `**` matches multiple path levels (only used at the end of event names)
|
|
91
91
|
|
|
92
92
|
```typescript
|
|
93
93
|
const events = new FastEvent();
|
|
94
94
|
|
|
95
95
|
// Match user/*/login
|
|
96
|
-
events.on(
|
|
97
|
-
console.log(
|
|
96
|
+
events.on("user/*/login", (message) => {
|
|
97
|
+
console.log("Any user type login:", message.payload);
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
// Match all events under user
|
|
101
|
-
events.on(
|
|
102
|
-
console.log(
|
|
101
|
+
events.on("user/**", (message) => {
|
|
102
|
+
console.log("All user-related events:", message.payload);
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
// Trigger events
|
|
106
|
-
events.emit(
|
|
107
|
-
events.emit(
|
|
106
|
+
events.emit("user/admin/login", { id: 1 }); // Both handlers will be called
|
|
107
|
+
events.emit("user/admin/profile/update", { name: "New" }); // Only the ** handler will be called
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
## Removing Listeners
|
|
@@ -113,21 +113,21 @@ events.emit('user/admin/profile/update', { name: 'New' }); // Only the ** handle
|
|
|
113
113
|
|
|
114
114
|
```typescript
|
|
115
115
|
// Return a subscriber object to remove the listener, recommended approach
|
|
116
|
-
const subscriber = events.on(
|
|
116
|
+
const subscriber = events.on("user/login", handler);
|
|
117
117
|
subscriber.off();
|
|
118
118
|
|
|
119
119
|
// Remove a specific listener
|
|
120
120
|
events.off(listener);
|
|
121
121
|
// Remove all listeners for a specific event
|
|
122
|
-
events.off(
|
|
122
|
+
events.off("user/login");
|
|
123
123
|
// Remove a specific listener for a specific event
|
|
124
|
-
events.off(
|
|
124
|
+
events.off("user/login", listener);
|
|
125
125
|
// Remove listeners using wildcard patterns
|
|
126
|
-
events.off(
|
|
126
|
+
events.off("user/*");
|
|
127
127
|
// Remove all listeners
|
|
128
128
|
events.offAll();
|
|
129
129
|
// Remove all listeners under a specific prefix
|
|
130
|
-
events.offAll(
|
|
130
|
+
events.offAll("user");
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
## Event Scopes
|
|
@@ -140,15 +140,15 @@ Scopes allow you to handle events within a specific namespace.
|
|
|
140
140
|
const events = new FastEvent();
|
|
141
141
|
|
|
142
142
|
// Create a user-related scope
|
|
143
|
-
const userScope = events.scope(
|
|
143
|
+
const userScope = events.scope("user");
|
|
144
144
|
|
|
145
145
|
// The following two approaches are equivalent:
|
|
146
|
-
userScope.on(
|
|
147
|
-
events.on(
|
|
146
|
+
userScope.on("login", handler);
|
|
147
|
+
events.on("user/login", handler);
|
|
148
148
|
|
|
149
149
|
// The following two approaches are also equivalent:
|
|
150
|
-
userScope.emit(
|
|
151
|
-
events.emit(
|
|
150
|
+
userScope.emit("login", data);
|
|
151
|
+
events.emit("user/login", data);
|
|
152
152
|
|
|
153
153
|
// Clear all listeners in the scope
|
|
154
154
|
userScope.offAll(); // Equivalent to events.offAll('user')
|
|
@@ -164,16 +164,16 @@ const events = new FastEvent();
|
|
|
164
164
|
async function waitForLogin() {
|
|
165
165
|
try {
|
|
166
166
|
// Wait for login event with a 5-second timeout
|
|
167
|
-
const userData = await events.waitFor(
|
|
168
|
-
console.log(
|
|
167
|
+
const userData = await events.waitFor("user/login", 5000);
|
|
168
|
+
console.log("User logged in:", userData);
|
|
169
169
|
} catch (error) {
|
|
170
|
-
console.log(
|
|
170
|
+
console.log("Login wait timeout");
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
waitForLogin();
|
|
175
175
|
// Later trigger the login event
|
|
176
|
-
events.emit(
|
|
176
|
+
events.emit("user/login", { id: 1, name: "Alice" });
|
|
177
177
|
```
|
|
178
178
|
|
|
179
179
|
## Event Hooks
|
|
@@ -184,23 +184,24 @@ events.emit('user/login', { id: 1, name: 'Alice' });
|
|
|
184
184
|
const otherEvents = new FastEvent();
|
|
185
185
|
const events = new FastEvent({
|
|
186
186
|
// Called when a new listener is added
|
|
187
|
-
|
|
188
|
-
console.log(
|
|
187
|
+
onAddBeforeListener: (type, listener, options) => {
|
|
188
|
+
console.log("Added new listener:", type);
|
|
189
189
|
// Return false to prevent the listener from being added
|
|
190
190
|
return false;
|
|
191
191
|
// Can directly return a FastEventSubscriber
|
|
192
192
|
// For example: transfer events starting with `@` to another FastEvent
|
|
193
|
-
if (type.startsWith(
|
|
193
|
+
if (type.startsWith("@")) {
|
|
194
194
|
return otherEvents.on(type, listener, options);
|
|
195
195
|
}
|
|
196
196
|
},
|
|
197
|
+
onAddBeforeListener
|
|
197
198
|
// Called when a listener is removed
|
|
198
199
|
onRemoveListener: (type, listener) => {
|
|
199
|
-
console.log(
|
|
200
|
+
console.log("Removed listener:", type);
|
|
200
201
|
},
|
|
201
202
|
// Called when listeners are cleared
|
|
202
203
|
onClearListeners: () => {
|
|
203
|
-
console.log(
|
|
204
|
+
console.log("All listeners cleared");
|
|
204
205
|
},
|
|
205
206
|
// Called when a listener throws an error
|
|
206
207
|
onListenerError: (error, listener, message, args) => {
|
|
@@ -208,19 +209,19 @@ const events = new FastEvent({
|
|
|
208
209
|
},
|
|
209
210
|
// Called before a listener executes
|
|
210
211
|
onBeforeExecuteListener: (message, args) => {
|
|
211
|
-
console.log(
|
|
212
|
+
console.log("Before executing event listener");
|
|
212
213
|
// Return false to prevent listener execution
|
|
213
214
|
return false;
|
|
214
215
|
|
|
215
216
|
// Forward events to another FastEvent
|
|
216
217
|
// For example: forward events starting with `@` to another FastEvent
|
|
217
|
-
if (type.startsWith(
|
|
218
|
+
if (type.startsWith("@")) {
|
|
218
219
|
return otherEvents.emit(message.type);
|
|
219
220
|
}
|
|
220
221
|
},
|
|
221
222
|
// Called after a listener executes
|
|
222
223
|
onAfterExecuteListener: (message, returns, listeners) => {
|
|
223
|
-
console.log(
|
|
224
|
+
console.log("After executing event listener");
|
|
224
225
|
// Can intercept and modify return values here
|
|
225
226
|
},
|
|
226
227
|
});
|
|
@@ -233,20 +234,20 @@ By default, all listeners are executed in parallel when an event is triggered.
|
|
|
233
234
|
`FastEvent` provides powerful listener execution mechanisms that allow developers to control how listeners are executed.
|
|
234
235
|
|
|
235
236
|
```typescript
|
|
236
|
-
import { race } from
|
|
237
|
+
import { race } from "fastevent/executors";
|
|
237
238
|
const events = new FastEvent({
|
|
238
239
|
executor: race(),
|
|
239
240
|
});
|
|
240
241
|
|
|
241
|
-
events.on(
|
|
242
|
+
events.on("task/start", async () => {
|
|
242
243
|
/* Time-consuming operation 1 */
|
|
243
244
|
});
|
|
244
|
-
events.on(
|
|
245
|
+
events.on("task/start", async () => {
|
|
245
246
|
/* Time-consuming operation 2 */
|
|
246
247
|
});
|
|
247
248
|
|
|
248
249
|
// The two listeners will execute in parallel, returning the fastest result
|
|
249
|
-
await events.emitAsync(
|
|
250
|
+
await events.emitAsync("task/start");
|
|
250
251
|
```
|
|
251
252
|
|
|
252
253
|
**Built-in Support**:
|
|
@@ -268,14 +269,14 @@ await events.emitAsync('task/start');
|
|
|
268
269
|
Listener pipes are used to wrap listener functions during event subscription to implement various common advanced features.
|
|
269
270
|
|
|
270
271
|
```typescript
|
|
271
|
-
import { queue } from
|
|
272
|
+
import { queue } from "fastevent/pipes";
|
|
272
273
|
const events = new FastEvent();
|
|
273
274
|
|
|
274
275
|
// default queue size is 10
|
|
275
276
|
events.on(
|
|
276
|
-
|
|
277
|
+
"data/update",
|
|
277
278
|
(data) => {
|
|
278
|
-
console.log(
|
|
279
|
+
console.log("Processing data:", data);
|
|
279
280
|
},
|
|
280
281
|
{
|
|
281
282
|
pipes: [queue({ size: 10 })],
|
|
@@ -303,29 +304,29 @@ const otherEmitter = new FastEvent();
|
|
|
303
304
|
const emitter = new FastEvent({
|
|
304
305
|
onAddListener: (type, listener, options) => {
|
|
305
306
|
// Subscription forwarding rule: when event name starts with `@/`, forward subscription to another `FastEvent` instance
|
|
306
|
-
if (type.startsWith(
|
|
307
|
+
if (type.startsWith("@/")) {
|
|
307
308
|
return otherEmitter.on(type.substring(2), listener, options);
|
|
308
309
|
}
|
|
309
310
|
},
|
|
310
311
|
onBeforeExecuteListener: (message, args) => {
|
|
311
312
|
// Event forwarding rule: when event name starts with `@/`, publish to another `FastEvent` instance
|
|
312
|
-
if (message.type.startsWith(
|
|
313
|
+
if (message.type.startsWith("@/")) {
|
|
313
314
|
message.type = message.type.substring(2);
|
|
314
315
|
return otherEmitter.emit(message, args);
|
|
315
316
|
}
|
|
316
317
|
},
|
|
317
318
|
});
|
|
318
319
|
const events: any[] = [];
|
|
319
|
-
otherEmitter.on(
|
|
320
|
+
otherEmitter.on("data", ({ payload }) => {
|
|
320
321
|
events.push(payload);
|
|
321
322
|
});
|
|
322
323
|
// Subscribe to otherEmitter's data event
|
|
323
|
-
emitter.on(
|
|
324
|
+
emitter.on("@/data", ({ payload }) => {
|
|
324
325
|
expect(payload).toBe(1);
|
|
325
326
|
events.push(payload);
|
|
326
327
|
});
|
|
327
328
|
// Publish data event to otherEmitter
|
|
328
|
-
const subscriber = emitter.emit(
|
|
329
|
+
const subscriber = emitter.emit("@/data", 1);
|
|
329
330
|
subscriber.off();
|
|
330
331
|
```
|
|
331
332
|
|
|
@@ -338,32 +339,32 @@ You can set metadata at different levels: global, scope level, or event-specific
|
|
|
338
339
|
```typescript
|
|
339
340
|
const events = new FastEvent({
|
|
340
341
|
meta: {
|
|
341
|
-
version:
|
|
342
|
-
environment:
|
|
342
|
+
version: "1.0",
|
|
343
|
+
environment: "production",
|
|
343
344
|
},
|
|
344
345
|
});
|
|
345
346
|
|
|
346
|
-
events.on(
|
|
347
|
-
console.log(
|
|
348
|
-
console.log(
|
|
347
|
+
events.on("user/login", (message) => {
|
|
348
|
+
console.log("Event data:", message.payload);
|
|
349
|
+
console.log("Metadata:", message.meta); // Includes type, version, and environment
|
|
349
350
|
});
|
|
350
351
|
|
|
351
352
|
// Using scope-level metadata
|
|
352
|
-
const userScope = events.scope(
|
|
353
|
-
meta: { domain:
|
|
353
|
+
const userScope = events.scope("user", {
|
|
354
|
+
meta: { domain: "user" },
|
|
354
355
|
});
|
|
355
356
|
// Add specific metadata when publishing events
|
|
356
357
|
userScope.emit(
|
|
357
|
-
|
|
358
|
-
{ userId:
|
|
358
|
+
"login",
|
|
359
|
+
{ userId: "123" },
|
|
359
360
|
{
|
|
360
361
|
meta: { timestamp: Date.now() }, // Event-specific metadata
|
|
361
362
|
},
|
|
362
363
|
);
|
|
363
364
|
|
|
364
365
|
// Listeners receive merged metadata
|
|
365
|
-
userScope.on(
|
|
366
|
-
console.log(
|
|
366
|
+
userScope.on("login", (message) => {
|
|
367
|
+
console.log("Metadata:", message.meta);
|
|
367
368
|
});
|
|
368
369
|
```
|
|
369
370
|
|
|
@@ -374,22 +375,22 @@ userScope.on('login', (message) => {
|
|
|
374
375
|
```typescript
|
|
375
376
|
// Define events with different payload types
|
|
376
377
|
interface ComplexEvents {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
378
|
+
"data/number": number;
|
|
379
|
+
"data/string": string;
|
|
380
|
+
"data/object": { value: any };
|
|
380
381
|
}
|
|
381
382
|
|
|
382
383
|
const events = new FastEvent<ComplexEvents>();
|
|
383
384
|
|
|
384
385
|
// TypeScript ensures type safety for each event
|
|
385
|
-
events.on(
|
|
386
|
+
events.on("data/number", (message) => {
|
|
386
387
|
const sum = message.payload + 1; // payload type is number
|
|
387
388
|
});
|
|
388
389
|
|
|
389
390
|
// All event emissions are type-checked
|
|
390
|
-
events.emit(
|
|
391
|
-
events.emit(
|
|
392
|
-
events.emit(
|
|
391
|
+
events.emit("data/number", 42);
|
|
392
|
+
events.emit("data/string", "hello");
|
|
393
|
+
events.emit("data/object", { value: true });
|
|
393
394
|
```
|
|
394
395
|
|
|
395
396
|
## Unit Testing
|