@x-oasis/emitter 0.1.34 → 0.1.36

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 CHANGED
@@ -1,22 +1,372 @@
1
1
  # @x-oasis/emitter
2
2
 
3
+ A TypeScript event emitter library with support for event management, lifecycle hooks, and integration with DOM and Node.js event emitters.
4
+
3
5
  ## Installation
4
6
 
5
7
  ```bash
6
8
  $ npm i @x-oasis/emitter
7
9
  ```
8
10
 
9
- ## How to use
11
+ ## API
12
+
13
+ ### `Emitter`
14
+
15
+ A class that manages multiple named events.
10
16
 
11
17
  ```typescript
12
- import Emitter from '@x-oasis/emitter'
18
+ class Emitter {
19
+ constructor(props: { name: string });
20
+ get name(): string;
21
+ register(eventName: string, eventProps?: EventProps): Event;
22
+ getEvent(eventName: string): Event | undefined;
23
+ dispose(): void;
24
+ }
13
25
  ```
14
26
 
15
- ## How to run test
27
+ ### `Event`
16
28
 
17
- ```bash
18
- $ pnpm test
29
+ A class representing a single event that can be subscribed to and fired.
30
+
31
+ ```typescript
32
+ class Event {
33
+ readonly name: string;
34
+ subscribe(listener: EventListener): IDisposable;
35
+ removeListener(listener: EventListener): void;
36
+ fire(...args: any[]): void;
37
+ dispose(): void;
38
+ }
39
+ ```
40
+
41
+ ### `fromNodeEvent()`
42
+
43
+ Creates an `Event` from a Node.js event emitter.
44
+
45
+ ```typescript
46
+ function fromNodeEvent(emitter: NodeEventEmitter, eventName: string): (listener: EventListener) => IDisposable;
47
+ ```
48
+
49
+ ### `EventProps`
50
+
51
+ Configuration options for creating an `Event`.
52
+
53
+ ```typescript
54
+ type EventProps = {
55
+ onWillAddFirstListener?: Function;
56
+ onDidAddFirstListener?: Function;
57
+ onDidAddListener?: Function;
58
+ onWillRemoveListener?: Function;
59
+ onDidRemoveLastListener?: Function;
60
+ coldTrigger?: boolean;
61
+ };
62
+ ```
63
+
64
+ ### `EventListener`
65
+
66
+ Type for event listener functions.
67
+
68
+ ```typescript
69
+ type EventListener = Function;
70
+ ```
71
+
72
+ ## Usage
73
+
74
+ ### Basic Event Usage
75
+
76
+ ```typescript
77
+ import { Event } from '@x-oasis/emitter';
78
+
79
+ // Create an event
80
+ const event = new Event({ name: 'myEvent' });
81
+
82
+ // Subscribe to the event
83
+ const disposable = event.subscribe((data) => {
84
+ console.log('Event fired:', data);
85
+ });
86
+
87
+ // Fire the event
88
+ event.fire('Hello, World!'); // Logs: "Event fired: Hello, World!"
89
+
90
+ // Unsubscribe
91
+ disposable.dispose();
92
+ ```
93
+
94
+ ### Using Emitter
95
+
96
+ ```typescript
97
+ import { Emitter } from '@x-oasis/emitter';
98
+
99
+ // Create an emitter
100
+ const emitter = new Emitter({ name: 'myEmitter' });
101
+
102
+ // Register an event
103
+ const clickEvent = emitter.register('click');
104
+
105
+ // Subscribe to the event
106
+ const disposable = clickEvent.subscribe((x, y) => {
107
+ console.log(`Clicked at (${x}, ${y})`);
108
+ });
109
+
110
+ // Fire the event
111
+ clickEvent.fire(100, 200); // Logs: "Clicked at (100, 200)"
112
+
113
+ // Get an existing event
114
+ const existingEvent = emitter.getEvent('click');
115
+ existingEvent?.fire(300, 400); // Logs: "Clicked at (300, 400)"
116
+
117
+ // Cleanup
118
+ emitter.dispose(); // Disposes all events
119
+ ```
120
+
121
+ ### Multiple Listeners
122
+
123
+ ```typescript
124
+ import { Event } from '@x-oasis/emitter';
125
+
126
+ const event = new Event({ name: 'data' });
127
+
128
+ // Add multiple listeners
129
+ const listener1 = (data: string) => console.log('Listener 1:', data);
130
+ const listener2 = (data: string) => console.log('Listener 2:', data);
131
+
132
+ const disposable1 = event.subscribe(listener1);
133
+ const disposable2 = event.subscribe(listener2);
134
+
135
+ event.fire('Hello');
136
+ // Logs: "Listener 1: Hello"
137
+ // Logs: "Listener 2: Hello"
138
+
139
+ // Remove a specific listener
140
+ event.removeListener(listener1);
141
+
142
+ event.fire('World');
143
+ // Logs: "Listener 2: World"
144
+ ```
145
+
146
+ ### Lifecycle Hooks
147
+
148
+ ```typescript
149
+ import { Event } from '@x-oasis/emitter';
150
+
151
+ const event = new Event({
152
+ name: 'lifecycle',
153
+ onWillAddFirstListener: () => {
154
+ console.log('First listener is about to be added');
155
+ },
156
+ onDidAddFirstListener: () => {
157
+ console.log('First listener was added');
158
+ },
159
+ onDidAddListener: () => {
160
+ console.log('A listener was added');
161
+ },
162
+ onWillRemoveListener: () => {
163
+ console.log('A listener is about to be removed');
164
+ },
165
+ onDidRemoveLastListener: () => {
166
+ console.log('Last listener was removed');
167
+ },
168
+ });
169
+
170
+ const disposable1 = event.subscribe(() => {});
171
+ // Logs: "First listener is about to be added"
172
+ // Logs: "First listener was added"
173
+ // Logs: "A listener was added"
174
+
175
+ const disposable2 = event.subscribe(() => {});
176
+ // Logs: "A listener was added"
177
+
178
+ disposable1.dispose();
179
+ // Logs: "A listener is about to be removed"
180
+
181
+ disposable2.dispose();
182
+ // Logs: "A listener is about to be removed"
183
+ // Logs: "Last listener was removed"
19
184
  ```
20
185
 
21
- ## Further Reading
22
- - [events](https://github.com/parcel-bundler/parcel/tree/v2/packages/utils/events)
186
+ ### Cold Trigger
187
+
188
+ When `coldTrigger` is enabled, new subscribers will immediately receive the last fired value.
189
+
190
+ ```typescript
191
+ import { Event } from '@x-oasis/emitter';
192
+
193
+ const event = new Event({
194
+ name: 'state',
195
+ coldTrigger: true,
196
+ });
197
+
198
+ // Fire before any listeners
199
+ event.fire('initial state');
200
+
201
+ // New listener receives the last value immediately
202
+ event.subscribe((state) => {
203
+ console.log('Current state:', state); // Logs: "Current state: initial state"
204
+ });
205
+
206
+ // Fire again
207
+ event.fire('updated state'); // Logs: "Current state: updated state"
208
+ ```
209
+
210
+ ### Integration with Node.js Event Emitter
211
+
212
+ ```typescript
213
+ import { fromNodeEvent } from '@x-oasis/emitter';
214
+ import { EventEmitter } from 'events';
215
+
216
+ const nodeEmitter = new EventEmitter();
217
+ const subscribe = fromNodeEvent(nodeEmitter, 'data');
218
+
219
+ // Subscribe to the Node.js event
220
+ const disposable = subscribe((data) => {
221
+ console.log('Received:', data);
222
+ });
223
+
224
+ // Emit from Node.js emitter
225
+ nodeEmitter.emit('data', 'Hello from Node.js'); // Logs: "Received: Hello from Node.js"
226
+
227
+ // Unsubscribe
228
+ disposable.dispose();
229
+ ```
230
+
231
+ ### Managing Multiple Events
232
+
233
+ ```typescript
234
+ import { Emitter } from '@x-oasis/emitter';
235
+
236
+ const emitter = new Emitter({ name: 'app' });
237
+
238
+ // Register multiple events
239
+ const clickEvent = emitter.register('click');
240
+ const hoverEvent = emitter.register('hover');
241
+ const keydownEvent = emitter.register('keydown');
242
+
243
+ // Subscribe to different events
244
+ clickEvent.subscribe((x, y) => {
245
+ console.log('Click:', x, y);
246
+ });
247
+
248
+ hoverEvent.subscribe((element) => {
249
+ console.log('Hover:', element);
250
+ });
251
+
252
+ keydownEvent.subscribe((key) => {
253
+ console.log('Key:', key);
254
+ });
255
+
256
+ // Fire events
257
+ clickEvent.fire(100, 200);
258
+ hoverEvent.fire(document.body);
259
+ keydownEvent.fire('Enter');
260
+
261
+ // Cleanup all events at once
262
+ emitter.dispose();
263
+ ```
264
+
265
+ ## Examples
266
+
267
+ ### Event-Driven Component
268
+
269
+ ```typescript
270
+ import { Emitter } from '@x-oasis/emitter';
271
+
272
+ class Component {
273
+ private emitter = new Emitter({ name: 'Component' });
274
+
275
+ on(eventName: string, listener: Function) {
276
+ const event = this.emitter.register(eventName);
277
+ return event.subscribe(listener);
278
+ }
279
+
280
+ emit(eventName: string, ...args: any[]) {
281
+ const event = this.emitter.getEvent(eventName);
282
+ event?.fire(...args);
283
+ }
284
+
285
+ destroy() {
286
+ this.emitter.dispose();
287
+ }
288
+ }
289
+
290
+ // Usage
291
+ const component = new Component();
292
+
293
+ component.on('update', (data) => {
294
+ console.log('Updated:', data);
295
+ });
296
+
297
+ component.emit('update', { value: 42 });
298
+ ```
299
+
300
+ ### State Management with Cold Trigger
301
+
302
+ ```typescript
303
+ import { Event } from '@x-oasis/emitter';
304
+
305
+ class StateManager {
306
+ private stateEvent = new Event({
307
+ name: 'state',
308
+ coldTrigger: true,
309
+ });
310
+
311
+ private state = { count: 0 };
312
+
313
+ getState() {
314
+ return this.state;
315
+ }
316
+
317
+ subscribe(listener: (state: any) => void) {
318
+ return this.stateEvent.subscribe(listener);
319
+ }
320
+
321
+ setState(newState: any) {
322
+ this.state = { ...this.state, ...newState };
323
+ this.stateEvent.fire(this.state);
324
+ }
325
+ }
326
+
327
+ // Usage
328
+ const manager = new StateManager();
329
+ manager.setState({ count: 1 });
330
+
331
+ // New subscriber gets current state immediately
332
+ manager.subscribe((state) => {
333
+ console.log('State:', state); // Logs: "State: { count: 1 }"
334
+ });
335
+ ```
336
+
337
+ ### Integration with DOM Events
338
+
339
+ ```typescript
340
+ import { Event } from '@x-oasis/emitter';
341
+
342
+ // Create a DOM event wrapper
343
+ function createDomEvent(element: HTMLElement, eventName: string) {
344
+ const event = new Event({
345
+ name: eventName,
346
+ onWillAddFirstListener: () => {
347
+ element.addEventListener(eventName, handler);
348
+ },
349
+ onDidRemoveLastListener: () => {
350
+ element.removeEventListener(eventName, handler);
351
+ },
352
+ });
353
+
354
+ const handler = (e: Event) => {
355
+ event.fire(e);
356
+ };
357
+
358
+ return event.subscribe;
359
+ }
360
+
361
+ // Usage
362
+ const button = document.querySelector('#myButton');
363
+ if (button) {
364
+ const subscribe = createDomEvent(button, 'click');
365
+ const disposable = subscribe((e) => {
366
+ console.log('Button clicked!', e);
367
+ });
368
+
369
+ // Later, unsubscribe
370
+ disposable.dispose();
371
+ }
372
+ ```
@@ -0,0 +1,15 @@
1
+ import Event from './Event';
2
+ import { EventProps } from './types';
3
+ export default class Emitter {
4
+ private _events;
5
+ private _disposed;
6
+ private _name;
7
+ constructor(props: {
8
+ name: string;
9
+ });
10
+ get name(): string;
11
+ register(eventName: string, eventProps?: EventProps): Event;
12
+ getEvent(eventName: string): Event;
13
+ dispose(): void;
14
+ }
15
+ export declare type IEvent = Event;
@@ -0,0 +1,19 @@
1
+ import { EventListener, EventProps } from './types';
2
+ export default class Event {
3
+ readonly name: string;
4
+ private _listeners;
5
+ private _onWillAddFirstListener?;
6
+ private _onDidAddFirstListener?;
7
+ private _onDidAddListener?;
8
+ private _onWillRemoveListener?;
9
+ private _onDidRemoveLastListener?;
10
+ private _coldTrigger?;
11
+ private _cacheCurrentValue?;
12
+ constructor(props: EventProps & {
13
+ name: string;
14
+ });
15
+ subscribe(listener: EventListener): import("@x-oasis/disposable").IDisposable;
16
+ removeListener(listener: EventListener): void;
17
+ dispose(): void;
18
+ fire(...args: any[]): void;
19
+ }
@@ -2,34 +2,214 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var Emitter = /*#__PURE__*/function () {
6
- function Emitter() {
7
- this.subscriptions = {};
5
+ var disposable = require('@x-oasis/disposable');
6
+
7
+ function _defineProperties(target, props) {
8
+ for (var i = 0; i < props.length; i++) {
9
+ var descriptor = props[i];
10
+ descriptor.enumerable = descriptor.enumerable || false;
11
+ descriptor.configurable = true;
12
+ if ("value" in descriptor) descriptor.writable = true;
13
+ Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
8
14
  }
9
- var _proto = Emitter.prototype;
10
- _proto.fire = function fire(event) {
11
- var cbs = this.subscriptions[event] || [];
12
- for (var _len = arguments.length, rest = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
13
- rest[_key - 1] = arguments[_key];
14
- }
15
- for (var i = 0; i < cbs.length; i++) {
16
- cbs[i].apply(this, rest);
15
+ }
16
+ function _createClass(Constructor, protoProps, staticProps) {
17
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
18
+ if (staticProps) _defineProperties(Constructor, staticProps);
19
+ Object.defineProperty(Constructor, "prototype", {
20
+ writable: false
21
+ });
22
+ return Constructor;
23
+ }
24
+ function _extends() {
25
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
26
+ for (var i = 1; i < arguments.length; i++) {
27
+ var source = arguments[i];
28
+ for (var key in source) {
29
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
30
+ target[key] = source[key];
31
+ }
32
+ }
17
33
  }
34
+ return target;
18
35
  };
19
- _proto.on = function on(event, cb) {
20
- var _this = this;
21
- if (!this.subscriptions[event]) this.subscriptions[event] = [cb];else this.subscriptions[event].push(cb);
36
+ return _extends.apply(this, arguments);
37
+ }
38
+ function _unsupportedIterableToArray(o, minLen) {
39
+ if (!o) return;
40
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
41
+ var n = Object.prototype.toString.call(o).slice(8, -1);
42
+ if (n === "Object" && o.constructor) n = o.constructor.name;
43
+ if (n === "Map" || n === "Set") return Array.from(o);
44
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
45
+ }
46
+ function _arrayLikeToArray(arr, len) {
47
+ if (len == null || len > arr.length) len = arr.length;
48
+ for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
49
+ return arr2;
50
+ }
51
+ function _createForOfIteratorHelperLoose(o, allowArrayLike) {
52
+ var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
53
+ if (it) return (it = it.call(o)).next.bind(it);
54
+ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
55
+ if (it) o = it;
56
+ var i = 0;
22
57
  return function () {
23
- var subscriptions = _this.subscriptions[event];
24
- var index = subscriptions.indexOf(cb);
25
- if (index !== -1) subscriptions.splice(index, 1);
58
+ if (i >= o.length) return {
59
+ done: true
60
+ };
61
+ return {
62
+ done: false,
63
+ value: o[i++]
64
+ };
26
65
  };
66
+ }
67
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
68
+ }
69
+ function _toPrimitive(input, hint) {
70
+ if (typeof input !== "object" || input === null) return input;
71
+ var prim = input[Symbol.toPrimitive];
72
+ if (prim !== undefined) {
73
+ var res = prim.call(input, hint || "default");
74
+ if (typeof res !== "object") return res;
75
+ throw new TypeError("@@toPrimitive must return a primitive value.");
76
+ }
77
+ return (hint === "string" ? String : Number)(input);
78
+ }
79
+ function _toPropertyKey(arg) {
80
+ var key = _toPrimitive(arg, "string");
81
+ return typeof key === "symbol" ? key : String(key);
82
+ }
83
+
84
+ var Event = /*#__PURE__*/function () {
85
+ function Event(props) {
86
+ this._listeners = [];
87
+ var name = props.name,
88
+ onWillAddFirstListener = props.onWillAddFirstListener,
89
+ onDidAddFirstListener = props.onDidAddFirstListener,
90
+ onDidAddListener = props.onDidAddListener,
91
+ onWillRemoveListener = props.onWillRemoveListener,
92
+ onDidRemoveLastListener = props.onDidRemoveLastListener,
93
+ coldTrigger = props.coldTrigger;
94
+ this.name = name;
95
+ this._coldTrigger = coldTrigger;
96
+ this._onWillAddFirstListener = onWillAddFirstListener;
97
+ this._onDidAddFirstListener = onDidAddFirstListener;
98
+ this._onDidAddListener = onDidAddListener;
99
+ this._onWillRemoveListener = onWillRemoveListener;
100
+ this._onDidRemoveLastListener = onDidRemoveLastListener;
101
+ this.subscribe = this.subscribe.bind(this);
102
+ }
103
+ var _proto = Event.prototype;
104
+ _proto.subscribe = function subscribe(listener) {
105
+ var _this = this;
106
+ if (!this._listeners.length) {
107
+ var _this$_onWillAddFirst;
108
+ (_this$_onWillAddFirst = this._onWillAddFirstListener) == null ? void 0 : _this$_onWillAddFirst.call(this);
109
+ }
110
+ var index = this._listeners.indexOf(listener);
111
+ if (index !== -1) {
112
+ console.error('add a duplicate listener');
113
+ } else {
114
+ var _this$_onDidAddFirstL, _this$_onDidAddListen;
115
+ this._listeners.push(listener);
116
+ if (this._listeners.length === 1) (_this$_onDidAddFirstL = this._onDidAddFirstListener) == null ? void 0 : _this$_onDidAddFirstL.call(this);
117
+ (_this$_onDidAddListen = this._onDidAddListener) == null ? void 0 : _this$_onDidAddListen.call(this);
118
+ if (this._coldTrigger && this._cacheCurrentValue) listener.apply(void 0, this._cacheCurrentValue);
119
+ }
120
+ return disposable.toDisposable(function () {
121
+ _this.removeListener(listener);
122
+ });
123
+ };
124
+ _proto.removeListener = function removeListener(listener) {
125
+ var _this$_onWillRemoveLi;
126
+ var index = this._listeners.indexOf(listener);
127
+ if (index === -1) return;
128
+ (_this$_onWillRemoveLi = this._onWillRemoveListener) == null ? void 0 : _this$_onWillRemoveLi.call(this);
129
+ this._listeners.splice(index, 1);
130
+ if (!this._listeners.length) {
131
+ var _this$_onDidRemoveLas;
132
+ (_this$_onDidRemoveLas = this._onDidRemoveLastListener) == null ? void 0 : _this$_onDidRemoveLas.call(this);
133
+ }
27
134
  };
28
- _proto.off = function off(event) {
29
- delete this.subscriptions[event];
135
+ _proto.dispose = function dispose() {
136
+ var _this$_onDidRemoveLas2;
137
+ this._listeners = [];
138
+ (_this$_onDidRemoveLas2 = this._onDidRemoveLastListener) == null ? void 0 : _this$_onDidRemoveLas2.call(this);
30
139
  };
140
+ _proto.fire = function fire() {
141
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
142
+ args[_key] = arguments[_key];
143
+ }
144
+ if (this._coldTrigger) {
145
+ this._cacheCurrentValue = args;
146
+ }
147
+ for (var _iterator = _createForOfIteratorHelperLoose(this._listeners), _step; !(_step = _iterator()).done;) {
148
+ var listener = _step.value;
149
+ listener.apply(void 0, args);
150
+ }
151
+ };
152
+ return Event;
153
+ }();
154
+
155
+ var Emitter = /*#__PURE__*/function () {
156
+ function Emitter(props) {
157
+ this._events = new Map();
158
+ this._disposed = false;
159
+ var _ref = props || {},
160
+ name = _ref.name;
161
+ this._name = name;
162
+ }
163
+ var _proto = Emitter.prototype;
164
+ _proto.register = function register(eventName, eventProps) {
165
+ if (this._events.has(eventName)) {
166
+ return this._events.get(eventName);
167
+ }
168
+ this._events.set(eventName, new Event(_extends({}, eventProps || {}, {
169
+ name: eventName
170
+ })));
171
+ return this._events.get(eventName);
172
+ };
173
+ _proto.getEvent = function getEvent(eventName) {
174
+ return this._events.get(eventName);
175
+ };
176
+ _proto.dispose = function dispose() {
177
+ if (this._disposed) return;
178
+ for (var _iterator = _createForOfIteratorHelperLoose(this._events), _step; !(_step = _iterator()).done;) {
179
+ var _step$value = _step.value,
180
+ event = _step$value[1];
181
+ event.dispose();
182
+ }
183
+ this._disposed = true;
184
+ };
185
+ _createClass(Emitter, [{
186
+ key: "name",
187
+ get: function get() {
188
+ return this._name;
189
+ }
190
+ }]);
31
191
  return Emitter;
32
192
  }();
33
193
 
34
- exports.default = Emitter;
194
+ function fromNodeEvent(emitter, eventName) {
195
+ var onFirstListenerAdd = function onFirstListenerAdd() {
196
+ return emitter.on(eventName, fn);
197
+ };
198
+ var onLastListenerRemove = function onLastListenerRemove() {
199
+ return emitter.removeListener(eventName, fn);
200
+ };
201
+ var event = new Event({
202
+ name: eventName,
203
+ onWillAddFirstListener: onFirstListenerAdd,
204
+ onDidRemoveLastListener: onLastListenerRemove
205
+ });
206
+ var fn = function fn() {
207
+ return event.fire.apply(event, arguments);
208
+ };
209
+ return event.subscribe;
210
+ }
211
+
212
+ exports.Emitter = Emitter;
213
+ exports.Event = Event;
214
+ exports.fromNodeEvent = fromNodeEvent;
35
215
  //# sourceMappingURL=emitter.cjs.development.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"emitter.cjs.development.js","sources":["../src/index.ts"],"sourcesContent":["class Emitter {\n public subscriptions: {\n [key: string]: any;\n } = {};\n\n fire(event, ...rest) {\n const cbs = this.subscriptions[event] || [];\n for (let i = 0; i < cbs.length; i++) {\n cbs[i].apply(this, rest); // eslint-disable-line\n }\n }\n\n on(event, cb) {\n if (!this.subscriptions[event]) this.subscriptions[event] = [cb];\n else this.subscriptions[event].push(cb);\n\n return () => {\n const subscriptions = this.subscriptions[event];\n const index = subscriptions.indexOf(cb);\n if (index !== -1) subscriptions.splice(index, 1);\n };\n }\n\n off(event) {\n delete this.subscriptions[event];\n }\n}\n\nexport default Emitter;\n"],"names":["Emitter","_proto","prototype","fire","event","cbs","subscriptions","_len","arguments","length","rest","Array","_key","i","apply","on","cb","push","_this","index","indexOf","splice","off"],"mappings":";;;;IAAMA,OAAO;EAAb,SAAAA;IACS,kBAAa,GAEhB,EAAE;;EAuBP,IAAAC,MAAA,GAAAD,OAAA,CAAAE,SAAA;EAAAD,MAAA,CArBCE,IAAI,GAAJ,SAAAA,KAAKC,KAAK;IACR,IAAMC,GAAG,GAAG,IAAI,CAACC,aAAa,CAACF,KAAK,CAAC,IAAI,EAAE;IAAC,SAAAG,IAAA,GAAAC,SAAA,CAAAC,MAAA,EAD/BC,IAAI,OAAAC,KAAA,CAAAJ,IAAA,OAAAA,IAAA,WAAAK,IAAA,MAAAA,IAAA,GAAAL,IAAA,EAAAK,IAAA;MAAJF,IAAI,CAAAE,IAAA,QAAAJ,SAAA,CAAAI,IAAA;;IAEjB,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGR,GAAG,CAACI,MAAM,EAAEI,CAAC,EAAE,EAAE;MACnCR,GAAG,CAACQ,CAAC,CAAC,CAACC,KAAK,CAAC,IAAI,EAAEJ,IAAI,CAAC;;GAE3B;EAAAT,MAAA,CAEDc,EAAE,GAAF,SAAAA,GAAGX,KAAK,EAAEY,EAAE;;IACV,IAAI,CAAC,IAAI,CAACV,aAAa,CAACF,KAAK,CAAC,EAAE,IAAI,CAACE,aAAa,CAACF,KAAK,CAAC,GAAG,CAACY,EAAE,CAAC,CAAC,KAC5D,IAAI,CAACV,aAAa,CAACF,KAAK,CAAC,CAACa,IAAI,CAACD,EAAE,CAAC;IAEvC,OAAO;MACL,IAAMV,aAAa,GAAGY,KAAI,CAACZ,aAAa,CAACF,KAAK,CAAC;MAC/C,IAAMe,KAAK,GAAGb,aAAa,CAACc,OAAO,CAACJ,EAAE,CAAC;MACvC,IAAIG,KAAK,KAAK,CAAC,CAAC,EAAEb,aAAa,CAACe,MAAM,CAACF,KAAK,EAAE,CAAC,CAAC;KACjD;GACF;EAAAlB,MAAA,CAEDqB,GAAG,GAAH,SAAAA,IAAIlB,KAAK;IACP,OAAO,IAAI,CAACE,aAAa,CAACF,KAAK,CAAC;GACjC;EAAA,OAAAJ,OAAA;AAAA;;;;"}
1
+ {"version":3,"file":"emitter.cjs.development.js","sources":["../src/Event.ts","../src/Emitter.ts","../src/fromNodeEvent.ts"],"sourcesContent":["import { toDisposable } from '@x-oasis/disposable';\nimport { EventListener, EventProps } from './types';\n\nexport default class Event {\n readonly name: string;\n\n private _listeners: EventListener[] = [];\n\n private _onWillAddFirstListener?: Function;\n\n private _onDidAddFirstListener?: Function;\n\n private _onDidAddListener?: Function;\n\n private _onWillRemoveListener?: Function;\n\n private _onDidRemoveLastListener?: Function;\n\n private _coldTrigger?: boolean;\n\n private _cacheCurrentValue?: any[] | undefined;\n\n constructor(props: EventProps & { name: string }) {\n const {\n name,\n onWillAddFirstListener,\n onDidAddFirstListener,\n onDidAddListener,\n onWillRemoveListener,\n onDidRemoveLastListener,\n coldTrigger,\n } = props;\n\n this.name = name;\n\n this._coldTrigger = coldTrigger;\n this._onWillAddFirstListener = onWillAddFirstListener;\n this._onDidAddFirstListener = onDidAddFirstListener;\n this._onDidAddListener = onDidAddListener;\n this._onWillRemoveListener = onWillRemoveListener;\n this._onDidRemoveLastListener = onDidRemoveLastListener;\n this.subscribe = this.subscribe.bind(this);\n }\n\n subscribe(listener: EventListener) {\n if (!this._listeners.length) {\n this._onWillAddFirstListener?.();\n }\n\n const index = this._listeners.indexOf(listener);\n if (index !== -1) {\n console.error('add a duplicate listener');\n } else {\n this._listeners.push(listener);\n if (this._listeners.length === 1) this._onDidAddFirstListener?.();\n this._onDidAddListener?.();\n if (this._coldTrigger && this._cacheCurrentValue)\n listener(...this._cacheCurrentValue);\n }\n\n return toDisposable(() => {\n this.removeListener(listener);\n });\n }\n\n removeListener(listener: EventListener) {\n const index = this._listeners.indexOf(listener);\n if (index === -1) return;\n this._onWillRemoveListener?.();\n\n this._listeners.splice(index, 1);\n if (!this._listeners.length) {\n this._onDidRemoveLastListener?.();\n }\n }\n\n dispose() {\n this._listeners = [];\n this._onDidRemoveLastListener?.();\n }\n\n fire(...args: any[]) {\n if (this._coldTrigger) {\n this._cacheCurrentValue = args;\n }\n for (const listener of this._listeners) {\n listener(...args);\n }\n }\n}\n","import Event from './Event';\nimport { EventProps } from './types';\n\nexport default class Emitter {\n private _events = new Map<string, Event>();\n\n private _disposed = false;\n\n private _name: string;\n\n constructor(props: { name: string }) {\n const { name } = props || {};\n this._name = name;\n }\n\n get name() {\n return this._name;\n }\n\n /**\n * 没有就注册,有就返回\n */\n register(eventName: string, eventProps?: EventProps) {\n if (this._events.has(eventName)) {\n return this._events.get(eventName) as Event;\n }\n\n this._events.set(\n eventName,\n new Event({\n ...(eventProps || {}),\n name: eventName,\n })\n );\n\n return this._events.get(eventName) as Event;\n }\n\n getEvent(eventName: string) {\n return this._events.get(eventName);\n }\n\n dispose() {\n if (this._disposed) return;\n for (const [_, event] of this._events) {\n event.dispose();\n }\n\n this._disposed = true;\n }\n}\n\nexport type IEvent = Event;\n","import Event from './Event';\n\nexport interface NodeEventEmitter {\n on(event: string | symbol, listener: Function): unknown;\n removeListener(event: string | symbol, listener: Function): unknown;\n}\n\n/**\n * Creates an {@link Event} from a node event emitter.\n */\nexport function fromNodeEvent(emitter: NodeEventEmitter, eventName: string) {\n // @ts-ignore\n const onFirstListenerAdd = () => emitter.on(eventName, fn);\n const onLastListenerRemove = () => emitter.removeListener(eventName, fn);\n const event = new Event({\n name: eventName,\n onWillAddFirstListener: onFirstListenerAdd,\n onDidRemoveLastListener: onLastListenerRemove,\n });\n\n const fn = (...args: any[]) => {\n return event.fire(...args);\n };\n\n return event.subscribe;\n}\n"],"names":["Event","props","name","onWillAddFirstListener","onDidAddFirstListener","onDidAddListener","onWillRemoveListener","onDidRemoveLastListener","coldTrigger","_coldTrigger","_onWillAddFirstListener","_onDidAddFirstListener","_onDidAddListener","_onWillRemoveListener","_onDidRemoveLastListener","subscribe","bind","_proto","prototype","listener","_listeners","length","_this$_onWillAddFirst","call","index","indexOf","console","error","_this$_onDidAddFirstL","_this$_onDidAddListen","push","_cacheCurrentValue","apply","toDisposable","_this","removeListener","_this$_onWillRemoveLi","splice","_this$_onDidRemoveLas","dispose","_this$_onDidRemoveLas2","fire","args","Array","_len","_key","arguments","_iterator","_createForOfIteratorHelperLoose","_step","done","value","Emitter","Map","_ref","_name","register","eventName","eventProps","_events","has","get","set","_extends","getEvent","_disposed","_step$value","_","event","_createClass","key","fromNodeEvent","emitter","onFirstListenerAdd","on","fn","onLastListenerRemove"],"mappings":"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"}