event-emission 0.1.0 → 0.2.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/README.md +228 -27
- package/dist/{eventful.d.ts → event-emission.d.ts} +22 -19
- package/dist/event-emission.d.ts.map +1 -0
- package/dist/factory.d.ts +1 -1
- package/dist/factory.d.ts.map +1 -1
- package/dist/index.cjs +811 -354
- package/dist/index.cjs.map +8 -8
- package/dist/index.d.ts +2 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +787 -348
- package/dist/index.js.map +8 -8
- package/dist/interoperability.cjs +1605 -0
- package/dist/interoperability.cjs.map +15 -0
- package/dist/{interop.d.ts → interoperability.d.ts} +12 -11
- package/dist/interoperability.d.ts.map +1 -0
- package/dist/interoperability.js +1555 -0
- package/dist/interoperability.js.map +15 -0
- package/dist/observable.cjs +286 -0
- package/dist/observable.cjs.map +11 -0
- package/dist/observable.d.ts +36 -0
- package/dist/observable.d.ts.map +1 -0
- package/dist/observable.js +253 -0
- package/dist/observable.js.map +11 -0
- package/dist/observe.cjs +344 -0
- package/dist/observe.cjs.map +10 -0
- package/dist/observe.d.ts +9 -4
- package/dist/observe.d.ts.map +1 -1
- package/dist/observe.js +313 -0
- package/dist/observe.js.map +10 -0
- package/dist/symbols.d.ts +1 -1
- package/dist/types.cjs +35 -0
- package/dist/types.cjs.map +9 -0
- package/dist/types.d.ts +105 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -0
- package/dist/types.js.map +9 -0
- package/package.json +27 -1
- package/src/{eventful.ts → event-emission.ts} +45 -28
- package/src/factory.ts +639 -269
- package/src/index.ts +7 -29
- package/src/{interop.ts → interoperability.ts} +55 -35
- package/src/observable.ts +310 -0
- package/src/observe.ts +70 -33
- package/src/symbols.ts +1 -1
- package/src/types.ts +130 -29
- package/dist/eventful.d.ts.map +0 -1
- package/dist/interop.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# Event Emission
|
|
2
2
|
|
|
3
|
+
**Event Emission** is a high-performance, type-safe event primitive designed to bridge the gap between three worlds: DOM `EventTarget`, TC39 `Observable`, and `AsyncIterator`. While standard event emitters often force you into a single consumption pattern, **Event Emission** gives you the freedom to dispatch once and consume however your logic demands—whether that's standard callbacks, reactive pipelines via RxJS, or clean `for await...of` loops. By treating events as a first-class, composable primitive rather than just a side-effect, it eliminates race conditions and shared mutable state, providing a unified, zero-dependency foundation for building resilient, concurrent applications in modern JavaScript and TypeScript environments.
|
|
4
|
+
|
|
3
5
|
A lightweight, zero-dependency, type-safe event system with DOM EventTarget ergonomics and TC39 Observable interoperability. Use one event source with callbacks, async iterators, and RxJS without losing TypeScript safety.
|
|
4
6
|
|
|
5
7
|
## Tasting notes
|
|
6
8
|
|
|
7
9
|
- **Typed events** - Event maps keep payloads and event names in sync
|
|
10
|
+
- **DOM compatible** - `EmissionEvent` is a superset of the built-in `Event`
|
|
8
11
|
- **Familiar API** - `addEventListener`, `removeEventListener`, `dispatchEvent`
|
|
9
|
-
- **Observable
|
|
12
|
+
- **TC39 Observable** - Fully compliant `Observable` implementation (passes all `es-observable-tests`)
|
|
10
13
|
- **Async iteration** - `for await...of` over events with backpressure options
|
|
11
14
|
- **Wildcard listeners** - Listen to `*` or namespaced `user:*` patterns
|
|
12
15
|
- **Observable state** - Proxy any object and emit change events automatically
|
|
@@ -56,16 +59,38 @@ events.dispatchEvent({
|
|
|
56
59
|
## Core concepts
|
|
57
60
|
|
|
58
61
|
- **Event map**: a TypeScript type that maps event names to payload types.
|
|
59
|
-
- **Event shape**: `{ type: string; detail: Payload }` for
|
|
62
|
+
- **Event shape**: `{ type: string; detail: Payload; bubbles?: boolean; cancelable?: boolean; composed?: boolean }` for dispatch.
|
|
60
63
|
- **Unsubscribe**: `addEventListener` returns a function to remove the listener.
|
|
61
64
|
|
|
62
65
|
## API overview
|
|
63
66
|
|
|
67
|
+
Core (`event-emission`):
|
|
68
|
+
|
|
64
69
|
- `createEventTarget<E>(options?)`
|
|
65
70
|
- `createEventTarget(target, { observe: true, ... })`
|
|
66
|
-
- `
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
- `EventEmission<E>` base class
|
|
72
|
+
|
|
73
|
+
Optional subpaths:
|
|
74
|
+
|
|
75
|
+
- `Observable<T>` compliant implementation (`event-emission/observable`)
|
|
76
|
+
- Interoperability: `fromEventTarget`, `forwardToEventTarget`, `pipe` (`event-emission/interoperability`)
|
|
77
|
+
- Observe utilities: `isObserved`, `getOriginal`, `setupEventForwarding` (`event-emission/observe`)
|
|
78
|
+
- Types-only exports (`event-emission/types`)
|
|
79
|
+
|
|
80
|
+
## Subpath exports
|
|
81
|
+
|
|
82
|
+
To keep the core entrypoint lean, optional features are exposed via subpath exports:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { Observable } from 'event-emission/observable';
|
|
86
|
+
import { getOriginal, isObserved, setupEventForwarding } from 'event-emission/observe';
|
|
87
|
+
import {
|
|
88
|
+
forwardToEventTarget,
|
|
89
|
+
fromEventTarget,
|
|
90
|
+
pipe,
|
|
91
|
+
} from 'event-emission/interoperability';
|
|
92
|
+
import type { EventTargetLike } from 'event-emission/types';
|
|
93
|
+
```
|
|
69
94
|
|
|
70
95
|
## createEventTarget
|
|
71
96
|
|
|
@@ -113,11 +138,29 @@ state.user.name = 'Grace'; // Triggers 'update' and 'update:user.name'
|
|
|
113
138
|
|
|
114
139
|
**Observe options:**
|
|
115
140
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
|
119
|
-
|
|
|
120
|
-
| `
|
|
141
|
+
Deep observation is enabled by default.
|
|
142
|
+
|
|
143
|
+
| Option | Type | Default | Description |
|
|
144
|
+
| --------------- | ------------------------------- | -------- | ------------------------------------------------------------------ |
|
|
145
|
+
| `observe` | `boolean` | `false` | Enable property change observation |
|
|
146
|
+
| `deep` | `boolean` | `true` | Observe nested objects |
|
|
147
|
+
| `cloneStrategy` | `'shallow' \| 'deep' \| 'path'` | `'path'` | How to clone previous state |
|
|
148
|
+
| `deepClone` | `<T>(value: T) => T` | - | Optional deep clone fallback when `structuredClone` is unavailable |
|
|
149
|
+
|
|
150
|
+
Note: `cloneStrategy: 'deep'` uses `structuredClone` by default, or `deepClone` if provided.
|
|
151
|
+
|
|
152
|
+
Example fallback:
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const state = createEventTarget(
|
|
156
|
+
{ count: 0, user: { name: 'Ada' } },
|
|
157
|
+
{
|
|
158
|
+
observe: true,
|
|
159
|
+
cloneStrategy: 'deep',
|
|
160
|
+
deepClone: (value) => JSON.parse(JSON.stringify(value)),
|
|
161
|
+
},
|
|
162
|
+
);
|
|
163
|
+
```
|
|
121
164
|
|
|
122
165
|
**Update event details:**
|
|
123
166
|
|
|
@@ -126,6 +169,29 @@ state.user.name = 'Grace'; // Triggers 'update' and 'update:user.name'
|
|
|
126
169
|
|
|
127
170
|
## Event listeners
|
|
128
171
|
|
|
172
|
+
### `on(type, options?)`
|
|
173
|
+
|
|
174
|
+
Creates an `Observable` for a specific event type. This follows the `ObservableEventTarget` proposal, allowing for powerful composition.
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
const clicks = button.on('click', { passive: true });
|
|
178
|
+
|
|
179
|
+
clicks.subscribe((event) => {
|
|
180
|
+
console.log('Clicked!', event.detail);
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Options:**
|
|
185
|
+
|
|
186
|
+
| Option | Type | Default | Description |
|
|
187
|
+
| -------------- | ------------- | ------- | -------------------------------------------------------------------------------------- |
|
|
188
|
+
| `capture` | `boolean` | `false` | If true, listen during the capture phase |
|
|
189
|
+
| `receiveError` | `boolean` | `false` | If true, listen for "error" events and forward them to the observer's error method |
|
|
190
|
+
| `handler` | `Function` | `null` | Optional function to run stateful actions (like `preventDefault()`) before dispatching |
|
|
191
|
+
| `once` | `boolean` | `false` | If true, the observable completes after the first event is dispatched |
|
|
192
|
+
| `passive` | `boolean` | `false` | Indicates that the callback will not cancel the event |
|
|
193
|
+
| `signal` | `AbortSignal` | - | Abort signal to remove the listener when aborted |
|
|
194
|
+
|
|
129
195
|
### `addEventListener(type, listener, options?)`
|
|
130
196
|
|
|
131
197
|
Adds a listener and returns an unsubscribe function.
|
|
@@ -138,18 +204,22 @@ const unsubscribe = events.addEventListener('message', (event) => {
|
|
|
138
204
|
unsubscribe();
|
|
139
205
|
```
|
|
140
206
|
|
|
141
|
-
**Options:**
|
|
207
|
+
**Options:** (or pass `true`/`false` for capture)
|
|
208
|
+
|
|
209
|
+
| Option | Type | Description |
|
|
210
|
+
| --------- | ------------- | -------------------------------------------- |
|
|
211
|
+
| `capture` | `boolean` | Listen during the capture phase |
|
|
212
|
+
| `once` | `boolean` | Remove listener after first invocation |
|
|
213
|
+
| `passive` | `boolean` | Listener will not call `preventDefault()` |
|
|
214
|
+
| `signal` | `AbortSignal` | Abort signal to remove listener when aborted |
|
|
142
215
|
|
|
143
|
-
|
|
144
|
-
| -------- | ------------- | -------------------------------------------- |
|
|
145
|
-
| `once` | `boolean` | Remove listener after first invocation |
|
|
146
|
-
| `signal` | `AbortSignal` | Abort signal to remove listener when aborted |
|
|
216
|
+
Note: `preventDefault()` only affects events dispatched with `cancelable: true`. `dispatchEvent` returns `false` when a cancelable event is prevented.
|
|
147
217
|
|
|
148
218
|
### `once(type, listener, options?)`
|
|
149
219
|
|
|
150
220
|
Adds a one-time listener.
|
|
151
221
|
|
|
152
|
-
### `removeEventListener(type, listener)`
|
|
222
|
+
### `removeEventListener(type, listener, options?)`
|
|
153
223
|
|
|
154
224
|
Removes a specific listener.
|
|
155
225
|
|
|
@@ -173,10 +243,24 @@ Wildcard events include `{ type: pattern, originalType, detail }`.
|
|
|
173
243
|
|
|
174
244
|
## Async iteration
|
|
175
245
|
|
|
246
|
+
You can use `for await...of` to consume events. This is great for stream-processing events with backpressure.
|
|
247
|
+
|
|
176
248
|
```typescript
|
|
177
|
-
|
|
249
|
+
// Simple iteration
|
|
250
|
+
for await (const event of events.events('message')) {
|
|
178
251
|
console.log('Received:', event.detail.text);
|
|
179
252
|
}
|
|
253
|
+
|
|
254
|
+
// With options for backpressure and cleanup
|
|
255
|
+
const iterator = events.events('message', {
|
|
256
|
+
bufferSize: 16,
|
|
257
|
+
overflowStrategy: 'drop-oldest',
|
|
258
|
+
signal: abortController.signal,
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
for await (const event of iterator) {
|
|
262
|
+
// ...
|
|
263
|
+
}
|
|
180
264
|
```
|
|
181
265
|
|
|
182
266
|
**Iterator options:**
|
|
@@ -221,6 +305,26 @@ observable
|
|
|
221
305
|
.subscribe(console.log);
|
|
222
306
|
```
|
|
223
307
|
|
|
308
|
+
### `Observable` class
|
|
309
|
+
|
|
310
|
+
A fully compliant implementation of the TC39 Observable proposal.
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
import { Observable } from 'event-emission/observable';
|
|
314
|
+
|
|
315
|
+
// Create from items
|
|
316
|
+
const numbers = Observable.of(1, 2, 3);
|
|
317
|
+
|
|
318
|
+
// Create from any iterable or observable-like
|
|
319
|
+
const fromArray = Observable.from([10, 20, 30]);
|
|
320
|
+
|
|
321
|
+
// Manual creation
|
|
322
|
+
const custom = new Observable((observer) => {
|
|
323
|
+
observer.next('Hello');
|
|
324
|
+
observer.complete();
|
|
325
|
+
});
|
|
326
|
+
```
|
|
327
|
+
|
|
224
328
|
## Lifecycle
|
|
225
329
|
|
|
226
330
|
### `complete()`
|
|
@@ -231,14 +335,14 @@ Marks the event target as complete, clears listeners, and ends iterators.
|
|
|
231
335
|
|
|
232
336
|
Removes all listeners without marking as complete.
|
|
233
337
|
|
|
234
|
-
##
|
|
338
|
+
## EventEmission base class
|
|
235
339
|
|
|
236
|
-
Extend `
|
|
340
|
+
Extend `EventEmission` to build typed emitters:
|
|
237
341
|
|
|
238
342
|
```typescript
|
|
239
|
-
import {
|
|
343
|
+
import { EventEmission } from 'event-emission';
|
|
240
344
|
|
|
241
|
-
class UserService extends
|
|
345
|
+
class UserService extends EventEmission<{
|
|
242
346
|
'user:created': { id: string; name: string };
|
|
243
347
|
'user:deleted': { id: string };
|
|
244
348
|
error: Error;
|
|
@@ -256,7 +360,7 @@ class UserService extends Eventful<{
|
|
|
256
360
|
### `fromEventTarget(domTarget, eventTypes, options?)`
|
|
257
361
|
|
|
258
362
|
```typescript
|
|
259
|
-
import { fromEventTarget } from 'event-emission';
|
|
363
|
+
import { fromEventTarget } from 'event-emission/interoperability';
|
|
260
364
|
|
|
261
365
|
type ButtonEvents = {
|
|
262
366
|
click: MouseEvent;
|
|
@@ -276,7 +380,8 @@ events.destroy();
|
|
|
276
380
|
### `forwardToEventTarget(source, domTarget, options?)`
|
|
277
381
|
|
|
278
382
|
```typescript
|
|
279
|
-
import { createEventTarget
|
|
383
|
+
import { createEventTarget } from 'event-emission';
|
|
384
|
+
import { forwardToEventTarget } from 'event-emission/interoperability';
|
|
280
385
|
|
|
281
386
|
const events = createEventTarget<{ custom: { value: number } }>();
|
|
282
387
|
const element = document.getElementById('target');
|
|
@@ -291,7 +396,8 @@ unsubscribe();
|
|
|
291
396
|
### `pipe(source, target, options?)`
|
|
292
397
|
|
|
293
398
|
```typescript
|
|
294
|
-
import { createEventTarget
|
|
399
|
+
import { createEventTarget } from 'event-emission';
|
|
400
|
+
import { pipe } from 'event-emission/interoperability';
|
|
295
401
|
|
|
296
402
|
const componentEvents = createEventTarget<{ ready: void }>();
|
|
297
403
|
const appBus = createEventTarget<{ ready: void }>();
|
|
@@ -301,7 +407,89 @@ const unsubscribe = pipe(componentEvents, appBus);
|
|
|
301
407
|
unsubscribe();
|
|
302
408
|
```
|
|
303
409
|
|
|
304
|
-
Note: `pipe(source, target)`
|
|
410
|
+
Note: Both `pipe(source, target)` and `events.pipe(target)` forward all events via a wildcard listener. Use a map function to transform events or return `null` to filter.
|
|
411
|
+
|
|
412
|
+
## React integration
|
|
413
|
+
|
|
414
|
+
**Event Emission** works beautifully with React's `useSyncExternalStore` for predictable, race-condition-free state synchronization.
|
|
415
|
+
|
|
416
|
+
### Observing an event emitter
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
import { useSyncExternalStore } from 'react';
|
|
420
|
+
import { createEventTarget } from 'event-emission';
|
|
421
|
+
|
|
422
|
+
const bus = createEventTarget<{ log: string }>();
|
|
423
|
+
|
|
424
|
+
function useBusEvent() {
|
|
425
|
+
return useSyncExternalStore(
|
|
426
|
+
(callback) => bus.addEventListener('log', callback),
|
|
427
|
+
() => getLatestLogValue(), // implementation depends on your needs
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Syncing with Observable State
|
|
433
|
+
|
|
434
|
+
The `observe` feature is perfect for building high-performance global stores or local controllers that live outside the React render cycle.
|
|
435
|
+
|
|
436
|
+
```typescript
|
|
437
|
+
import { useSyncExternalStore } from 'react';
|
|
438
|
+
import { createEventTarget } from 'event-emission';
|
|
439
|
+
|
|
440
|
+
// 1. Create your store outside of React
|
|
441
|
+
const store = createEventTarget(
|
|
442
|
+
{ count: 0, lastUpdated: new Date() },
|
|
443
|
+
{ observe: true }
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
// 2. Create a generic hook to sync with any observed target
|
|
447
|
+
export function useObservable<T extends object>(target: T) {
|
|
448
|
+
return useSyncExternalStore(
|
|
449
|
+
(onStoreChange) => (target as any).addEventListener('update', onStoreChange),
|
|
450
|
+
() => target
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// 3. Components re-render only when the store actually mutates
|
|
455
|
+
function Counter() {
|
|
456
|
+
const state = useObservable(store);
|
|
457
|
+
return (
|
|
458
|
+
<button onClick={() => state.count++}>
|
|
459
|
+
Count is {state.count}
|
|
460
|
+
</button>
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## Svelte integration
|
|
466
|
+
|
|
467
|
+
**Event Emission** works naturally with Svelte 5 Runes to create reactive stores that live outside your component tree.
|
|
468
|
+
|
|
469
|
+
### Creating a Reactive Rune
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
import { createEventTarget } from 'event-emission';
|
|
473
|
+
|
|
474
|
+
// 1. Define your external state
|
|
475
|
+
const store = createEventTarget({ count: 0 }, { observe: true });
|
|
476
|
+
|
|
477
|
+
// 2. Create a generic Rune to sync with any observed target
|
|
478
|
+
export function useObservable<T extends object>(target: T) {
|
|
479
|
+
let state = $state(target);
|
|
480
|
+
|
|
481
|
+
$effect(() => {
|
|
482
|
+
return (target as any).addEventListener('update', () => {
|
|
483
|
+
state = target; // Trigger Svelte reactivity
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
return state;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// 3. Use it in your components
|
|
491
|
+
const state = useObservable(store);
|
|
492
|
+
```
|
|
305
493
|
|
|
306
494
|
## Utilities
|
|
307
495
|
|
|
@@ -309,23 +497,36 @@ Note: `pipe(source, target)` forwards all events via a wildcard listener. The in
|
|
|
309
497
|
|
|
310
498
|
Checks if an object is an observed proxy.
|
|
311
499
|
|
|
500
|
+
```typescript
|
|
501
|
+
import { isObserved } from 'event-emission/observe';
|
|
502
|
+
```
|
|
503
|
+
|
|
312
504
|
### `getOriginal(proxy)`
|
|
313
505
|
|
|
314
506
|
Returns the original unproxied object.
|
|
315
507
|
|
|
508
|
+
```typescript
|
|
509
|
+
import { getOriginal } from 'event-emission/observe';
|
|
510
|
+
```
|
|
511
|
+
|
|
316
512
|
## TypeScript types
|
|
317
513
|
|
|
318
514
|
```typescript
|
|
319
515
|
import type {
|
|
320
|
-
|
|
516
|
+
EmissionEvent,
|
|
321
517
|
EventTargetLike,
|
|
322
518
|
ObservableLike,
|
|
323
519
|
Observer,
|
|
324
520
|
Subscription,
|
|
325
521
|
WildcardEvent,
|
|
326
522
|
AddEventListenerOptionsLike,
|
|
523
|
+
} from 'event-emission/types';
|
|
524
|
+
|
|
525
|
+
import type {
|
|
327
526
|
ObservableEventMap,
|
|
328
527
|
PropertyChangeDetail,
|
|
329
528
|
ArrayMutationDetail,
|
|
330
|
-
} from 'event-emission';
|
|
529
|
+
} from 'event-emission/observe';
|
|
530
|
+
|
|
531
|
+
import type { Subscriber, SubscriptionObserver } from 'event-emission/observable';
|
|
331
532
|
```
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SymbolObservable } from './symbols';
|
|
2
|
-
import type { AddEventListenerOptionsLike,
|
|
2
|
+
import type { AddEventListenerOptionsLike, DispatchEventInput, DOMEventLike, EmissionEvent, EventListenerLike, EventListenerOptionsLike, EventsIteratorOptions, EventTargetLike, ObservableLike, Observer, OnOptions, Subscription, WildcardEvent } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Abstract base class for typed event emitters with DOM EventTarget
|
|
5
5
|
* and TC39 Observable compatibility.
|
|
@@ -7,7 +7,7 @@ import type { AddEventListenerOptionsLike, EventfulEvent, EventsIteratorOptions,
|
|
|
7
7
|
* Extend this class to create custom event emitters with typed events.
|
|
8
8
|
* The class provides:
|
|
9
9
|
* - DOM EventTarget compatible API (addEventListener, removeEventListener, dispatchEvent)
|
|
10
|
-
* - TC39 Observable
|
|
10
|
+
* - TC39 Observable interoperability (subscribe, Symbol.observable)
|
|
11
11
|
* - Async iteration support (events() method)
|
|
12
12
|
* - Wildcard listeners for namespaced events
|
|
13
13
|
* - Lifecycle management (complete(), completed)
|
|
@@ -21,7 +21,7 @@ import type { AddEventListenerOptionsLike, EventfulEvent, EventsIteratorOptions,
|
|
|
21
21
|
* @example Basic usage
|
|
22
22
|
* ```typescript
|
|
23
23
|
* // Define your emitter with typed events
|
|
24
|
-
* class UserService extends
|
|
24
|
+
* class UserService extends EventEmission<{
|
|
25
25
|
* 'user:created': { id: string; name: string };
|
|
26
26
|
* 'user:deleted': { id: string };
|
|
27
27
|
* error: Error;
|
|
@@ -39,7 +39,7 @@ import type { AddEventListenerOptionsLike, EventfulEvent, EventsIteratorOptions,
|
|
|
39
39
|
* });
|
|
40
40
|
* ```
|
|
41
41
|
*
|
|
42
|
-
* @example TC39 Observable
|
|
42
|
+
* @example TC39 Observable interoperability
|
|
43
43
|
* ```typescript
|
|
44
44
|
* const service = new UserService();
|
|
45
45
|
*
|
|
@@ -64,32 +64,36 @@ import type { AddEventListenerOptionsLike, EventfulEvent, EventsIteratorOptions,
|
|
|
64
64
|
* }
|
|
65
65
|
* ```
|
|
66
66
|
*/
|
|
67
|
-
export declare abstract class
|
|
67
|
+
export declare abstract class EventEmission<E extends Record<string, any>> {
|
|
68
68
|
#private;
|
|
69
69
|
/**
|
|
70
|
-
* Returns this observable for Symbol.observable
|
|
70
|
+
* Returns this observable for Symbol.observable interoperability.
|
|
71
71
|
*/
|
|
72
|
-
[SymbolObservable]: () => ObservableLike<
|
|
72
|
+
[SymbolObservable]: () => ObservableLike<EmissionEvent<E[keyof E]>>;
|
|
73
73
|
constructor();
|
|
74
74
|
/**
|
|
75
75
|
* Adds an event listener for the specified event type.
|
|
76
76
|
* Returns an unsubscribe function for convenience.
|
|
77
77
|
*/
|
|
78
|
-
addEventListener<K extends keyof E & string>(type: K, listener:
|
|
78
|
+
addEventListener<K extends keyof E & string>(type: K, listener: EventListenerLike<EmissionEvent<E[K], K>> | null, options?: AddEventListenerOptionsLike | boolean): () => void;
|
|
79
79
|
/**
|
|
80
80
|
* Removes an event listener for the specified event type.
|
|
81
81
|
*/
|
|
82
|
-
removeEventListener<K extends keyof E & string>(type: K, listener:
|
|
82
|
+
removeEventListener<K extends keyof E & string>(type: K, listener: EventListenerLike<EmissionEvent<E[K], K>> | null, options?: EventListenerOptionsLike | boolean): void;
|
|
83
83
|
/**
|
|
84
84
|
* Dispatches an event to all registered listeners.
|
|
85
85
|
* Returns false if the emitter has been completed, true otherwise.
|
|
86
86
|
*/
|
|
87
|
-
dispatchEvent<K extends keyof E & string>(event:
|
|
87
|
+
dispatchEvent<K extends keyof E & string>(event: DispatchEventInput<E[K], K> | DOMEventLike): boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Returns an observable for the specified event type.
|
|
90
|
+
*/
|
|
91
|
+
on<K extends keyof E & string>(type: K, options?: OnOptions | boolean): ObservableLike<EmissionEvent<E[K], K>>;
|
|
88
92
|
/**
|
|
89
93
|
* Adds a one-time listener for the specified event type.
|
|
90
94
|
* Returns an unsubscribe function.
|
|
91
95
|
*/
|
|
92
|
-
once<K extends keyof E & string>(type: K, listener:
|
|
96
|
+
once<K extends keyof E & string>(type: K, listener: EventListenerLike<EmissionEvent<E[K], K>> | null, options?: Omit<AddEventListenerOptionsLike, 'once'> | boolean): () => void;
|
|
93
97
|
/**
|
|
94
98
|
* Removes all listeners, or those of the specified event type.
|
|
95
99
|
*/
|
|
@@ -100,10 +104,9 @@ export declare abstract class Eventful<E extends Record<string, any>> {
|
|
|
100
104
|
clear(): void;
|
|
101
105
|
/**
|
|
102
106
|
* Pipe events from this emitter to another target.
|
|
103
|
-
*
|
|
104
|
-
* Events for types registered after piping won't be forwarded automatically.
|
|
107
|
+
* Forwards all events. If mapFn returns null, the event is skipped.
|
|
105
108
|
*/
|
|
106
|
-
pipe<T extends Record<string, any>>(target: EventTargetLike<T>, mapFn?: <K extends keyof E & string>(event:
|
|
109
|
+
pipe<T extends Record<string, any>>(target: EventTargetLike<T>, mapFn?: <K extends keyof E & string>(event: EmissionEvent<E[K], K>) => DispatchEventInput<T[keyof T & string], keyof T & string> | null): () => void;
|
|
107
110
|
/**
|
|
108
111
|
* Adds a wildcard listener that receives events matching the pattern.
|
|
109
112
|
* Use '*' for all events, or 'namespace:*' for namespaced events.
|
|
@@ -116,15 +119,15 @@ export declare abstract class Eventful<E extends Record<string, any>> {
|
|
|
116
119
|
/**
|
|
117
120
|
* Subscribes an observer to all events (untyped).
|
|
118
121
|
*/
|
|
119
|
-
subscribe(observerOrNext: Observer<
|
|
122
|
+
subscribe(observerOrNext: Observer<EmissionEvent<E[keyof E]>> | ((value: EmissionEvent<E[keyof E]>) => void)): Subscription;
|
|
120
123
|
/**
|
|
121
124
|
* Subscribes an observer to events of a specific type (typed).
|
|
122
125
|
*/
|
|
123
|
-
subscribe<K extends keyof E & string>(type: K, observerOrNext?: Observer<
|
|
126
|
+
subscribe<K extends keyof E & string>(type: K, observerOrNext?: Observer<EmissionEvent<E[K], K>> | ((value: EmissionEvent<E[K], K>) => void), error?: (err: unknown) => void, completeHandler?: () => void): Subscription;
|
|
124
127
|
/**
|
|
125
128
|
* Returns an observable that emits all events.
|
|
126
129
|
*/
|
|
127
|
-
toObservable(): ObservableLike<
|
|
130
|
+
toObservable(): ObservableLike<EmissionEvent<E[keyof E]>>;
|
|
128
131
|
/**
|
|
129
132
|
* Marks the emitter as complete. Invokes complete() on all observable subscribers,
|
|
130
133
|
* ends all async iterators, and suppresses further emits/dispatches.
|
|
@@ -148,6 +151,6 @@ export declare abstract class Eventful<E extends Record<string, any>> {
|
|
|
148
151
|
* }
|
|
149
152
|
* ```
|
|
150
153
|
*/
|
|
151
|
-
events<K extends keyof E & string>(type: K, options?: EventsIteratorOptions): AsyncIterableIterator<
|
|
154
|
+
events<K extends keyof E & string>(type: K, options?: EventsIteratorOptions): AsyncIterableIterator<EmissionEvent<E[K], K>>;
|
|
152
155
|
}
|
|
153
|
-
//# sourceMappingURL=
|
|
156
|
+
//# sourceMappingURL=event-emission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-emission.d.ts","sourceRoot":"","sources":["../src/event-emission.ts"],"names":[],"mappings":"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"}
|
package/dist/factory.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export interface CreateEventTargetOptions {
|
|
|
15
15
|
* Extends CreateEventTargetOptions with proxy observation settings.
|
|
16
16
|
*
|
|
17
17
|
* @property observe - Must be true to enable observation mode.
|
|
18
|
-
* @property deep - If true, nested objects are also observed (default:
|
|
18
|
+
* @property deep - If true, nested objects are also observed (default: true).
|
|
19
19
|
* @property cloneStrategy - Strategy for cloning previous state: 'shallow', 'deep', or 'path'.
|
|
20
20
|
*/
|
|
21
21
|
export interface CreateEventTargetObserveOptions extends CreateEventTargetOptions, ObserveOptions {
|
package/dist/factory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACpB,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EAIV,eAAe,EAOhB,MAAM,SAAS,CAAC;AAyCjB;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,+EAA+E;IAC/E,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1D;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,+BACf,SAAQ,wBAAwB,EAAE,cAAc;IAChD,+CAA+C;IAC/C,OAAO,EAAE,IAAI,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC7D,IAAI,CAAC,EAAE,wBAAwB,GAC9B,eAAe,CAAC,CAAC,CAAC,CAAC;AAEtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAChD,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,+BAA+B,GACpC,CAAC,GAAG,eAAe,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC"}
|