@xyo-network/module-events 2.75.3 → 2.75.4
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/browser/Events/Events.js +30 -29
- package/dist/browser/Events/Events.js.map +1 -1
- package/dist/browser/Events/index.js +261 -1
- package/dist/browser/Events/index.js.map +1 -1
- package/dist/browser/index.js +261 -2
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/model/index.js +0 -1
- package/dist/browser/model/index.js.map +1 -1
- package/dist/docs.json +105 -105
- package/package.json +9 -9
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
// src/Events/Events.ts
|
|
1
2
|
import { assertEx } from "@xylabs/assert";
|
|
2
3
|
import { forget } from "@xylabs/forget";
|
|
3
4
|
import { Base } from "@xyo-network/core";
|
|
4
5
|
import { handleError } from "@xyo-network/error";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
var resolvedPromise = Promise.resolve();
|
|
7
|
+
var isMetaEvent = (eventName) => eventName === "listenerAdded" || eventName === "listenerRemoved";
|
|
8
|
+
var Events = class _Events extends Base {
|
|
8
9
|
static anyMap = /* @__PURE__ */ new WeakMap();
|
|
9
10
|
static eventsMap = /* @__PURE__ */ new WeakMap();
|
|
10
11
|
static canEmitMetaEvents = false;
|
|
@@ -34,18 +35,18 @@ class Events extends Base {
|
|
|
34
35
|
});
|
|
35
36
|
}
|
|
36
37
|
super(mutatedParams);
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
_Events.anyMap.set(this, /* @__PURE__ */ new Set());
|
|
39
|
+
_Events.eventsMap.set(this, /* @__PURE__ */ new Map());
|
|
39
40
|
}
|
|
40
41
|
static get isDebugEnabled() {
|
|
41
42
|
if (typeof globalThis.process?.env !== "object") {
|
|
42
|
-
return
|
|
43
|
+
return _Events.isGlobalDebugEnabled;
|
|
43
44
|
}
|
|
44
45
|
const { env } = globalThis.process ?? { env: {} };
|
|
45
|
-
return env.DEBUG === "events" || env.DEBUG === "*" ||
|
|
46
|
+
return env.DEBUG === "events" || env.DEBUG === "*" || _Events.isGlobalDebugEnabled;
|
|
46
47
|
}
|
|
47
48
|
static set isDebugEnabled(newValue) {
|
|
48
|
-
|
|
49
|
+
_Events.isGlobalDebugEnabled = newValue;
|
|
49
50
|
}
|
|
50
51
|
get debug() {
|
|
51
52
|
return this.params.debug;
|
|
@@ -60,10 +61,10 @@ class Events extends Base {
|
|
|
60
61
|
set.clear();
|
|
61
62
|
}
|
|
62
63
|
} else {
|
|
63
|
-
|
|
64
|
-
for (const [eventName2, listeners] of assertEx(
|
|
64
|
+
_Events.anyMap.get(this)?.clear();
|
|
65
|
+
for (const [eventName2, listeners] of assertEx(_Events.eventsMap.get(this)).entries()) {
|
|
65
66
|
listeners.clear();
|
|
66
|
-
|
|
67
|
+
_Events.eventsMap.get(this)?.delete(eventName2);
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
}
|
|
@@ -74,15 +75,15 @@ class Events extends Base {
|
|
|
74
75
|
async emitMetaEvent(eventName, eventArgs) {
|
|
75
76
|
if (isMetaEvent(eventName)) {
|
|
76
77
|
try {
|
|
77
|
-
|
|
78
|
+
_Events.canEmitMetaEvents = true;
|
|
78
79
|
await this.emitMetaEventInternal(eventName, eventArgs);
|
|
79
80
|
} finally {
|
|
80
|
-
|
|
81
|
+
_Events.canEmitMetaEvents = false;
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
async emitSerial(eventName, eventArgs) {
|
|
85
|
-
if (isMetaEvent(eventName) && !
|
|
86
|
+
if (isMetaEvent(eventName) && !_Events.canEmitMetaEvents) {
|
|
86
87
|
throw new TypeError("`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`");
|
|
87
88
|
}
|
|
88
89
|
const filterMatch = (args, filter) => {
|
|
@@ -99,7 +100,7 @@ class Events extends Base {
|
|
|
99
100
|
this.logIfDebugEnabled("emitSerial", eventName, eventArgs);
|
|
100
101
|
const listeners = this.getListeners(eventName) ?? /* @__PURE__ */ new Set();
|
|
101
102
|
const filteredListeners = [...listeners.values()].filter((value) => value.filter ? filterMatch(eventArgs, value.filter) : true).map((info) => info.listener);
|
|
102
|
-
const anyListeners = assertEx(
|
|
103
|
+
const anyListeners = assertEx(_Events.anyMap.get(this));
|
|
103
104
|
const staticListeners = [...filteredListeners];
|
|
104
105
|
const staticAnyListeners = [...anyListeners];
|
|
105
106
|
await resolvedPromise;
|
|
@@ -116,18 +117,18 @@ class Events extends Base {
|
|
|
116
117
|
let count = 0;
|
|
117
118
|
for (const eventName of eventNamesArray) {
|
|
118
119
|
if (typeof eventName === "string") {
|
|
119
|
-
count += assertEx(
|
|
120
|
+
count += assertEx(_Events.anyMap.get(this)).size + (this.getListeners(eventName)?.size ?? 0);
|
|
120
121
|
continue;
|
|
121
122
|
}
|
|
122
|
-
count += assertEx(
|
|
123
|
-
for (const value of assertEx(
|
|
123
|
+
count += assertEx(_Events.anyMap.get(this)).size;
|
|
124
|
+
for (const value of assertEx(_Events.eventsMap.get(this)).values()) {
|
|
124
125
|
count += value.size;
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
return count;
|
|
128
129
|
}
|
|
129
130
|
logIfDebugEnabled(type, eventName, eventArgs) {
|
|
130
|
-
if (
|
|
131
|
+
if (_Events.isDebugEnabled || this.debug?.enabled) {
|
|
131
132
|
this.debug?.logger?.(type, this.debug.name, eventName, eventArgs);
|
|
132
133
|
}
|
|
133
134
|
}
|
|
@@ -138,7 +139,7 @@ class Events extends Base {
|
|
|
138
139
|
if (set) {
|
|
139
140
|
set.delete(listener);
|
|
140
141
|
if (set.size === 0) {
|
|
141
|
-
const events =
|
|
142
|
+
const events = _Events.eventsMap.get(this);
|
|
142
143
|
events?.delete(eventName);
|
|
143
144
|
}
|
|
144
145
|
}
|
|
@@ -150,7 +151,7 @@ class Events extends Base {
|
|
|
150
151
|
}
|
|
151
152
|
offAny(listener) {
|
|
152
153
|
this.logIfDebugEnabled("unsubscribeAny", void 0, void 0);
|
|
153
|
-
const typedMap =
|
|
154
|
+
const typedMap = _Events.anyMap.get(this);
|
|
154
155
|
typedMap?.delete(listener);
|
|
155
156
|
forget(this.emitMetaEvent("listenerRemoved", { listener }));
|
|
156
157
|
}
|
|
@@ -160,7 +161,7 @@ class Events extends Base {
|
|
|
160
161
|
let set = this.getListeners(eventName);
|
|
161
162
|
if (!set) {
|
|
162
163
|
set = /* @__PURE__ */ new Set();
|
|
163
|
-
const events =
|
|
164
|
+
const events = _Events.eventsMap.get(this);
|
|
164
165
|
events?.set(eventName, set);
|
|
165
166
|
}
|
|
166
167
|
set.add({ filter, listener });
|
|
@@ -173,7 +174,7 @@ class Events extends Base {
|
|
|
173
174
|
}
|
|
174
175
|
onAny(listener) {
|
|
175
176
|
this.logIfDebugEnabled("subscribeAny", void 0, void 0);
|
|
176
|
-
|
|
177
|
+
_Events.anyMap.get(this)?.add(listener);
|
|
177
178
|
forget(this.emitMetaEvent("listenerAdded", { listener }));
|
|
178
179
|
return this.offAny.bind(this, listener);
|
|
179
180
|
}
|
|
@@ -186,13 +187,13 @@ class Events extends Base {
|
|
|
186
187
|
return this.off.bind(this, eventName, subListener);
|
|
187
188
|
}
|
|
188
189
|
async emitInternal(eventName, eventArgs, filter) {
|
|
189
|
-
if (isMetaEvent(eventName) && !
|
|
190
|
+
if (isMetaEvent(eventName) && !_Events.canEmitMetaEvents) {
|
|
190
191
|
throw new TypeError("`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`");
|
|
191
192
|
}
|
|
192
193
|
this.logIfDebugEnabled("emit", eventName, eventArgs);
|
|
193
194
|
const listeners = this.getListeners(eventName) ?? /* @__PURE__ */ new Set();
|
|
194
195
|
const filteredListeners = [...listeners.values()].filter((value) => filter ? value.listener : true).map((info) => info.listener);
|
|
195
|
-
const anyListeners = assertEx(
|
|
196
|
+
const anyListeners = assertEx(_Events.anyMap.get(this));
|
|
196
197
|
const staticListeners = [...filteredListeners];
|
|
197
198
|
const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners];
|
|
198
199
|
await resolvedPromise;
|
|
@@ -208,13 +209,13 @@ class Events extends Base {
|
|
|
208
209
|
]);
|
|
209
210
|
}
|
|
210
211
|
async emitMetaEventInternal(eventName, eventArgs) {
|
|
211
|
-
if (isMetaEvent(eventName) && !
|
|
212
|
+
if (isMetaEvent(eventName) && !_Events.canEmitMetaEvents) {
|
|
212
213
|
throw new TypeError("`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`");
|
|
213
214
|
}
|
|
214
215
|
this.logIfDebugEnabled("emit", eventName, eventArgs);
|
|
215
216
|
const listeners = this.getListeners(eventName) ?? /* @__PURE__ */ new Set();
|
|
216
217
|
const filteredListeners = [...listeners.values()].map((info) => info.listener);
|
|
217
|
-
const anyListeners = assertEx(
|
|
218
|
+
const anyListeners = assertEx(_Events.anyMap.get(this));
|
|
218
219
|
const staticListeners = [...filteredListeners];
|
|
219
220
|
const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners];
|
|
220
221
|
await resolvedPromise;
|
|
@@ -230,7 +231,7 @@ class Events extends Base {
|
|
|
230
231
|
]);
|
|
231
232
|
}
|
|
232
233
|
getListeners(eventName) {
|
|
233
|
-
const events = assertEx(
|
|
234
|
+
const events = assertEx(_Events.eventsMap.get(this));
|
|
234
235
|
if (!events.has(eventName)) {
|
|
235
236
|
return;
|
|
236
237
|
}
|
|
@@ -254,7 +255,7 @@ class Events extends Base {
|
|
|
254
255
|
});
|
|
255
256
|
}
|
|
256
257
|
}
|
|
257
|
-
}
|
|
258
|
+
};
|
|
258
259
|
export {
|
|
259
260
|
Events
|
|
260
261
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/Events/Events.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { forget } from '@xylabs/forget'\nimport { Base, BaseParams } from '@xyo-network/core'\nimport { handleError } from '@xyo-network/error'\n\nimport { EventAnyListener, EventArgs, EventData, EventFunctions, EventListener, EventName } from '../model'\n\n/**\nEmittery can collect and log debug information.\n\nTo enable this feature set the `DEBUG` environment variable to `emittery` or `*`. Additionally, you can set the static `isDebugEnabled` variable to true on the Emittery class, or `myEmitter.debug.enabled` on an instance of it for debugging a single instance.\n\nSee API for more information on how debugging works.\n*/\nexport type DebugLogger = (type: string, debugName: string, eventName?: EventName, eventData?: EventArgs) => void\n\nexport type EventListenerInfo<TEventArgs extends EventArgs = EventArgs> = {\n filter?: TEventArgs\n listener: EventListener<TEventArgs>\n}\n\n/**\nConfigure debug options of an instance.\n*/\nexport type DebugOptions = {\n enabled?: boolean\n logger?: DebugLogger\n readonly name: string\n}\n\nconst resolvedPromise = Promise.resolve()\n\nexport type MetaEventData<TEventData extends EventData> = {\n listenerAdded: {\n eventName?: keyof TEventData\n listener: EventListener<TEventData[keyof TEventData]> | EventAnyListener<TEventData[keyof TEventData]>\n }\n listenerRemoved: {\n eventName?: keyof TEventData\n listener: EventListener<TEventData[keyof TEventData]> | EventAnyListener<TEventData[keyof TEventData]>\n }\n}\n\nconst isMetaEvent = (eventName: EventName) => eventName === 'listenerAdded' || eventName === 'listenerRemoved'\n\nexport type EventsParams = BaseParams<{ readonly debug?: DebugOptions }>\n\nexport class Events<TEventData extends EventData = EventData> extends Base<EventsParams> implements EventFunctions<TEventData> {\n protected static anyMap = new WeakMap<object, Set<EventAnyListener>>()\n protected static eventsMap = new WeakMap<object, Map<EventName, Set<EventListenerInfo>>>()\n\n private static canEmitMetaEvents = false\n private static isGlobalDebugEnabled = false\n\n //this is here to be able to query the type, not use\n eventData = {} as TEventData\n\n constructor(params: EventsParams = {}) {\n const mutatedParams = { ...params }\n if (mutatedParams.debug) {\n mutatedParams.debug.logger =\n mutatedParams.debug.logger ??\n ((type: string, debugName: string, eventName?: EventName, eventData?: EventArgs) => {\n let eventDataString: string\n let eventNameString: string | undefined\n try {\n eventDataString = JSON.stringify(eventData)\n } catch {\n eventDataString = `Object with the following keys failed to stringify: ${Object.keys(eventData ?? {}).join(',')}`\n }\n\n if (typeof eventName === 'symbol' || typeof eventName === 'number') {\n eventNameString = eventName.toString()\n } else {\n eventNameString = eventName\n }\n\n const currentTime = new Date()\n const logTime = `${currentTime.getHours()}:${currentTime.getMinutes()}:${currentTime.getSeconds()}.${currentTime.getMilliseconds()}`\n this.logger.log(`[${logTime}][events:${type}][${debugName}] Event Name: ${eventNameString}\\n\\tdata: ${eventDataString}`)\n })\n }\n super(mutatedParams)\n Events.anyMap.set(this, new Set<EventAnyListener>())\n Events.eventsMap.set(this, new Map<keyof TEventData, Set<EventListenerInfo>>())\n }\n\n static get isDebugEnabled() {\n // In a browser environment, `globalThis.process` can potentially reference a DOM Element with a `#process` ID,\n // so instead of just type checking `globalThis.process`, we need to make sure that `globalThis.process.env` exists.\n\n if (typeof globalThis.process?.env !== 'object') {\n return Events.isGlobalDebugEnabled\n }\n\n const { env } = globalThis.process ?? { env: {} }\n return env.DEBUG === 'events' || env.DEBUG === '*' || Events.isGlobalDebugEnabled\n }\n\n static set isDebugEnabled(newValue) {\n Events.isGlobalDebugEnabled = newValue\n }\n\n get debug() {\n return this.params.debug\n }\n\n clearListeners(eventNames: keyof TEventData | (keyof TEventData)[]) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n\n for (const eventName of eventNamesArray) {\n this.logIfDebugEnabled('clear', eventName, undefined)\n\n if (typeof eventName === 'string' || typeof eventName === 'symbol' || typeof eventName === 'number') {\n const set = this.getListeners(eventName)\n if (set) {\n set.clear()\n }\n } else {\n Events.anyMap.get(this)?.clear()\n\n for (const [eventName, listeners] of assertEx(Events.eventsMap.get(this)).entries()) {\n listeners.clear()\n Events.eventsMap.get(this)?.delete(eventName)\n }\n }\n }\n }\n\n async emit<TEventName extends keyof TEventData>(eventName: TEventName, eventArgs: TEventData[TEventName]) {\n await this.emitInternal(eventName, eventArgs)\n }\n\n async emitMetaEvent<TEventName extends keyof MetaEventData<TEventData>>(eventName: TEventName, eventArgs: MetaEventData<TEventData>[TEventName]) {\n if (isMetaEvent(eventName)) {\n try {\n Events.canEmitMetaEvents = true\n await this.emitMetaEventInternal(eventName, eventArgs)\n } finally {\n Events.canEmitMetaEvents = false\n }\n }\n }\n\n async emitSerial<TEventName extends keyof TEventData>(eventName: TEventName, eventArgs: TEventData[TEventName]) {\n if (isMetaEvent(eventName) && !Events.canEmitMetaEvents) {\n throw new TypeError('`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`')\n }\n\n const filterMatch = (args: TEventData[TEventName], filter: TEventData[TEventName]) => {\n if (filter) {\n switch (typeof filter) {\n case 'object':\n return Object.entries(args).reduce((prev, [key, value]) => ((filter as Record<PropertyKey, unknown>)[key] === value ? true : prev), false)\n default:\n return args === filter\n }\n }\n return true\n }\n\n this.logIfDebugEnabled('emitSerial', eventName, eventArgs)\n\n const listeners = this.getListeners(eventName) ?? new Set()\n const filteredListeners = [...listeners.values()]\n .filter((value) => (value.filter ? filterMatch(eventArgs, value.filter as TEventData[TEventName]) : true))\n .map((info) => info.listener)\n const anyListeners = assertEx(Events.anyMap.get(this))\n const staticListeners = [...filteredListeners]\n const staticAnyListeners = [...anyListeners]\n\n await resolvedPromise\n\n for (const listener of staticListeners) {\n await this.safeCallListener(eventName, eventArgs, listener)\n }\n\n for (const listener of staticAnyListeners) {\n await this.safeCallAnyListener(eventName, eventArgs, listener)\n }\n }\n\n //TODO: Make test for this\n listenerCount(eventNames?: keyof TEventData | (keyof TEventData)[]) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n let count = 0\n\n for (const eventName of eventNamesArray) {\n if (typeof eventName === 'string') {\n count += assertEx(Events.anyMap.get(this)).size + (this.getListeners(eventName)?.size ?? 0)\n\n continue\n }\n\n count += assertEx(Events.anyMap.get(this)).size\n\n for (const value of assertEx(Events.eventsMap.get(this)).values()) {\n count += value.size\n }\n }\n\n return count\n }\n\n logIfDebugEnabled<TEventName extends EventName>(type: string, eventName?: TEventName, eventArgs?: EventArgs) {\n if (Events.isDebugEnabled || this.debug?.enabled) {\n this.debug?.logger?.(type, this.debug.name, eventName, eventArgs)\n }\n }\n\n off<TEventName extends keyof TEventData, TEventListener = EventListener<TEventData[TEventName]>>(\n eventNames: TEventName | TEventName[],\n listener: TEventListener,\n ) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n for (const eventName of eventNamesArray) {\n const set = this.getListeners(eventName) as Set<TEventListener>\n if (set) {\n set.delete(listener)\n if (set.size === 0) {\n const events = Events.eventsMap.get(this)\n events?.delete(eventName)\n }\n }\n\n this.logIfDebugEnabled('unsubscribe', eventName, undefined)\n\n if (!isMetaEvent(eventName)) {\n forget(this.emitMetaEvent('listenerRemoved', { eventName, listener: listener as EventListener }))\n }\n }\n }\n\n offAny(listener: EventAnyListener) {\n this.logIfDebugEnabled('unsubscribeAny', undefined, undefined)\n\n const typedMap = Events.anyMap.get(this) as Set<EventAnyListener<TEventData[keyof TEventData]>>\n typedMap?.delete(listener)\n forget(this.emitMetaEvent('listenerRemoved', { listener: listener as EventAnyListener }))\n }\n\n on<TEventName extends keyof TEventData = keyof TEventData>(\n eventNames: TEventName | TEventName[],\n listener: EventListener<TEventData[TEventName]>,\n filter?: TEventData[TEventName],\n ) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n for (const eventName of eventNamesArray) {\n let set = this.getListeners(eventName)\n if (!set) {\n set = new Set()\n const events = Events.eventsMap.get(this)\n events?.set(eventName, set)\n }\n\n set.add({ filter, listener: listener as EventListener })\n\n this.logIfDebugEnabled('subscribe', eventName, undefined)\n\n if (!isMetaEvent(eventName)) {\n forget(this.emitMetaEvent('listenerAdded', { eventName, listener: listener as EventListener }))\n }\n }\n\n return this.off.bind(this, eventNames, listener as EventListener)\n }\n\n onAny(listener: EventAnyListener) {\n this.logIfDebugEnabled('subscribeAny', undefined, undefined)\n\n Events.anyMap.get(this)?.add(listener as EventAnyListener)\n forget(this.emitMetaEvent('listenerAdded', { listener: listener as EventAnyListener }))\n return this.offAny.bind(this, listener as EventAnyListener)\n }\n\n once<TEventName extends keyof TEventData>(eventName: TEventName, listener: EventListener<TEventData[TEventName]>) {\n const subListener = async (args: TEventData[TEventName]) => {\n this.off(eventName, subListener)\n await this.safeCallListener(eventName, args, listener)\n }\n this.on(eventName, subListener)\n return this.off.bind(this, eventName, subListener as EventListener)\n }\n\n private async emitInternal<TEventName extends keyof TEventData, TEventArgs extends TEventData[TEventName]>(\n eventName: TEventName,\n eventArgs: TEventArgs,\n filter?: TEventArgs,\n ) {\n if (isMetaEvent(eventName) && !Events.canEmitMetaEvents) {\n throw new TypeError('`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`')\n }\n\n this.logIfDebugEnabled('emit', eventName, eventArgs)\n\n const listeners = this.getListeners(eventName) ?? new Set()\n const filteredListeners = [...listeners.values()].filter((value) => (filter ? value.listener : true)).map((info) => info.listener)\n const anyListeners = assertEx(Events.anyMap.get(this))\n const staticListeners = [...filteredListeners]\n const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners]\n\n await resolvedPromise\n await Promise.all([\n ...staticListeners.map(async (listener) => {\n await this.safeCallListener(eventName, eventArgs, listener)\n }),\n ...staticAnyListeners.map(async (listener) => {\n if (anyListeners.has(listener)) {\n await this.safeCallAnyListener(eventName, eventArgs, listener)\n }\n }),\n ])\n }\n\n private async emitMetaEventInternal<TEventName extends keyof MetaEventData<TEventData>>(\n eventName: TEventName,\n eventArgs: MetaEventData<TEventData>[TEventName],\n ) {\n if (isMetaEvent(eventName) && !Events.canEmitMetaEvents) {\n throw new TypeError('`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`')\n }\n\n this.logIfDebugEnabled('emit', eventName, eventArgs)\n\n const listeners = this.getListeners(eventName) ?? new Set()\n const filteredListeners = [...listeners.values()].map((info) => info.listener)\n const anyListeners = assertEx(Events.anyMap.get(this))\n const staticListeners = [...filteredListeners]\n const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners]\n\n await resolvedPromise\n await Promise.all([\n ...staticListeners.map(async (listener) => {\n await this.safeCallListener(eventName, eventArgs, listener)\n }),\n ...staticAnyListeners.map(async (listener) => {\n if (anyListeners.has(listener)) {\n await this.safeCallAnyListener(eventName, eventArgs, listener)\n }\n }),\n ])\n }\n\n private getListeners<TEventName extends keyof TEventData>(eventName: TEventName) {\n const events = assertEx(Events.eventsMap.get(this))\n if (!events.has(eventName)) {\n return\n }\n\n return events.get(eventName)\n }\n\n private async safeCallAnyListener<TEventData extends EventData, TEventName extends keyof EventData>(\n eventName: TEventName,\n eventArgs: TEventData[TEventName],\n listener: EventAnyListener<TEventData[TEventName]>,\n ) {\n try {\n return await listener(eventName, eventArgs)\n } catch (ex) {\n handleError(ex, (error) => {\n this.logger?.error(`Listener[${String(eventName)}] Excepted: ${error.message}`)\n })\n }\n }\n\n private async safeCallListener<TEventData extends EventData, TEventName extends keyof EventData>(\n eventName: TEventName,\n eventArgs: TEventData[TEventName],\n listener: EventListener<TEventData[TEventName]>,\n ) {\n try {\n return await listener(eventArgs)\n } catch (ex) {\n handleError(ex, (error) => {\n this.logger?.error(`Listener[${String(eventName)}] Excepted: ${error.message}`)\n })\n }\n }\n}\n"],"mappings":"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","names":["eventName"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/Events/Events.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { forget } from '@xylabs/forget'\nimport { Base, BaseParams } from '@xyo-network/core'\nimport { handleError } from '@xyo-network/error'\n\nimport { EventAnyListener, EventArgs, EventData, EventFunctions, EventListener, EventName } from '../model'\n\n/**\nEmittery can collect and log debug information.\n\nTo enable this feature set the `DEBUG` environment variable to `emittery` or `*`. Additionally, you can set the static `isDebugEnabled` variable to true on the Emittery class, or `myEmitter.debug.enabled` on an instance of it for debugging a single instance.\n\nSee API for more information on how debugging works.\n*/\nexport type DebugLogger = (type: string, debugName: string, eventName?: EventName, eventData?: EventArgs) => void\n\nexport type EventListenerInfo<TEventArgs extends EventArgs = EventArgs> = {\n filter?: TEventArgs\n listener: EventListener<TEventArgs>\n}\n\n/**\nConfigure debug options of an instance.\n*/\nexport type DebugOptions = {\n enabled?: boolean\n logger?: DebugLogger\n readonly name: string\n}\n\nconst resolvedPromise = Promise.resolve()\n\nexport type MetaEventData<TEventData extends EventData> = {\n listenerAdded: {\n eventName?: keyof TEventData\n listener: EventListener<TEventData[keyof TEventData]> | EventAnyListener<TEventData[keyof TEventData]>\n }\n listenerRemoved: {\n eventName?: keyof TEventData\n listener: EventListener<TEventData[keyof TEventData]> | EventAnyListener<TEventData[keyof TEventData]>\n }\n}\n\nconst isMetaEvent = (eventName: EventName) => eventName === 'listenerAdded' || eventName === 'listenerRemoved'\n\nexport type EventsParams = BaseParams<{ readonly debug?: DebugOptions }>\n\nexport class Events<TEventData extends EventData = EventData> extends Base<EventsParams> implements EventFunctions<TEventData> {\n protected static anyMap = new WeakMap<object, Set<EventAnyListener>>()\n protected static eventsMap = new WeakMap<object, Map<EventName, Set<EventListenerInfo>>>()\n\n private static canEmitMetaEvents = false\n private static isGlobalDebugEnabled = false\n\n //this is here to be able to query the type, not use\n eventData = {} as TEventData\n\n constructor(params: EventsParams = {}) {\n const mutatedParams = { ...params }\n if (mutatedParams.debug) {\n mutatedParams.debug.logger =\n mutatedParams.debug.logger ??\n ((type: string, debugName: string, eventName?: EventName, eventData?: EventArgs) => {\n let eventDataString: string\n let eventNameString: string | undefined\n try {\n eventDataString = JSON.stringify(eventData)\n } catch {\n eventDataString = `Object with the following keys failed to stringify: ${Object.keys(eventData ?? {}).join(',')}`\n }\n\n if (typeof eventName === 'symbol' || typeof eventName === 'number') {\n eventNameString = eventName.toString()\n } else {\n eventNameString = eventName\n }\n\n const currentTime = new Date()\n const logTime = `${currentTime.getHours()}:${currentTime.getMinutes()}:${currentTime.getSeconds()}.${currentTime.getMilliseconds()}`\n this.logger.log(`[${logTime}][events:${type}][${debugName}] Event Name: ${eventNameString}\\n\\tdata: ${eventDataString}`)\n })\n }\n super(mutatedParams)\n Events.anyMap.set(this, new Set<EventAnyListener>())\n Events.eventsMap.set(this, new Map<keyof TEventData, Set<EventListenerInfo>>())\n }\n\n static get isDebugEnabled() {\n // In a browser environment, `globalThis.process` can potentially reference a DOM Element with a `#process` ID,\n // so instead of just type checking `globalThis.process`, we need to make sure that `globalThis.process.env` exists.\n\n if (typeof globalThis.process?.env !== 'object') {\n return Events.isGlobalDebugEnabled\n }\n\n const { env } = globalThis.process ?? { env: {} }\n return env.DEBUG === 'events' || env.DEBUG === '*' || Events.isGlobalDebugEnabled\n }\n\n static set isDebugEnabled(newValue) {\n Events.isGlobalDebugEnabled = newValue\n }\n\n get debug() {\n return this.params.debug\n }\n\n clearListeners(eventNames: keyof TEventData | (keyof TEventData)[]) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n\n for (const eventName of eventNamesArray) {\n this.logIfDebugEnabled('clear', eventName, undefined)\n\n if (typeof eventName === 'string' || typeof eventName === 'symbol' || typeof eventName === 'number') {\n const set = this.getListeners(eventName)\n if (set) {\n set.clear()\n }\n } else {\n Events.anyMap.get(this)?.clear()\n\n for (const [eventName, listeners] of assertEx(Events.eventsMap.get(this)).entries()) {\n listeners.clear()\n Events.eventsMap.get(this)?.delete(eventName)\n }\n }\n }\n }\n\n async emit<TEventName extends keyof TEventData>(eventName: TEventName, eventArgs: TEventData[TEventName]) {\n await this.emitInternal(eventName, eventArgs)\n }\n\n async emitMetaEvent<TEventName extends keyof MetaEventData<TEventData>>(eventName: TEventName, eventArgs: MetaEventData<TEventData>[TEventName]) {\n if (isMetaEvent(eventName)) {\n try {\n Events.canEmitMetaEvents = true\n await this.emitMetaEventInternal(eventName, eventArgs)\n } finally {\n Events.canEmitMetaEvents = false\n }\n }\n }\n\n async emitSerial<TEventName extends keyof TEventData>(eventName: TEventName, eventArgs: TEventData[TEventName]) {\n if (isMetaEvent(eventName) && !Events.canEmitMetaEvents) {\n throw new TypeError('`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`')\n }\n\n const filterMatch = (args: TEventData[TEventName], filter: TEventData[TEventName]) => {\n if (filter) {\n switch (typeof filter) {\n case 'object':\n return Object.entries(args).reduce((prev, [key, value]) => ((filter as Record<PropertyKey, unknown>)[key] === value ? true : prev), false)\n default:\n return args === filter\n }\n }\n return true\n }\n\n this.logIfDebugEnabled('emitSerial', eventName, eventArgs)\n\n const listeners = this.getListeners(eventName) ?? new Set()\n const filteredListeners = [...listeners.values()]\n .filter((value) => (value.filter ? filterMatch(eventArgs, value.filter as TEventData[TEventName]) : true))\n .map((info) => info.listener)\n const anyListeners = assertEx(Events.anyMap.get(this))\n const staticListeners = [...filteredListeners]\n const staticAnyListeners = [...anyListeners]\n\n await resolvedPromise\n\n for (const listener of staticListeners) {\n await this.safeCallListener(eventName, eventArgs, listener)\n }\n\n for (const listener of staticAnyListeners) {\n await this.safeCallAnyListener(eventName, eventArgs, listener)\n }\n }\n\n //TODO: Make test for this\n listenerCount(eventNames?: keyof TEventData | (keyof TEventData)[]) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n let count = 0\n\n for (const eventName of eventNamesArray) {\n if (typeof eventName === 'string') {\n count += assertEx(Events.anyMap.get(this)).size + (this.getListeners(eventName)?.size ?? 0)\n\n continue\n }\n\n count += assertEx(Events.anyMap.get(this)).size\n\n for (const value of assertEx(Events.eventsMap.get(this)).values()) {\n count += value.size\n }\n }\n\n return count\n }\n\n logIfDebugEnabled<TEventName extends EventName>(type: string, eventName?: TEventName, eventArgs?: EventArgs) {\n if (Events.isDebugEnabled || this.debug?.enabled) {\n this.debug?.logger?.(type, this.debug.name, eventName, eventArgs)\n }\n }\n\n off<TEventName extends keyof TEventData, TEventListener = EventListener<TEventData[TEventName]>>(\n eventNames: TEventName | TEventName[],\n listener: TEventListener,\n ) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n for (const eventName of eventNamesArray) {\n const set = this.getListeners(eventName) as Set<TEventListener>\n if (set) {\n set.delete(listener)\n if (set.size === 0) {\n const events = Events.eventsMap.get(this)\n events?.delete(eventName)\n }\n }\n\n this.logIfDebugEnabled('unsubscribe', eventName, undefined)\n\n if (!isMetaEvent(eventName)) {\n forget(this.emitMetaEvent('listenerRemoved', { eventName, listener: listener as EventListener }))\n }\n }\n }\n\n offAny(listener: EventAnyListener) {\n this.logIfDebugEnabled('unsubscribeAny', undefined, undefined)\n\n const typedMap = Events.anyMap.get(this) as Set<EventAnyListener<TEventData[keyof TEventData]>>\n typedMap?.delete(listener)\n forget(this.emitMetaEvent('listenerRemoved', { listener: listener as EventAnyListener }))\n }\n\n on<TEventName extends keyof TEventData = keyof TEventData>(\n eventNames: TEventName | TEventName[],\n listener: EventListener<TEventData[TEventName]>,\n filter?: TEventData[TEventName],\n ) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n for (const eventName of eventNamesArray) {\n let set = this.getListeners(eventName)\n if (!set) {\n set = new Set()\n const events = Events.eventsMap.get(this)\n events?.set(eventName, set)\n }\n\n set.add({ filter, listener: listener as EventListener })\n\n this.logIfDebugEnabled('subscribe', eventName, undefined)\n\n if (!isMetaEvent(eventName)) {\n forget(this.emitMetaEvent('listenerAdded', { eventName, listener: listener as EventListener }))\n }\n }\n\n return this.off.bind(this, eventNames, listener as EventListener)\n }\n\n onAny(listener: EventAnyListener) {\n this.logIfDebugEnabled('subscribeAny', undefined, undefined)\n\n Events.anyMap.get(this)?.add(listener as EventAnyListener)\n forget(this.emitMetaEvent('listenerAdded', { listener: listener as EventAnyListener }))\n return this.offAny.bind(this, listener as EventAnyListener)\n }\n\n once<TEventName extends keyof TEventData>(eventName: TEventName, listener: EventListener<TEventData[TEventName]>) {\n const subListener = async (args: TEventData[TEventName]) => {\n this.off(eventName, subListener)\n await this.safeCallListener(eventName, args, listener)\n }\n this.on(eventName, subListener)\n return this.off.bind(this, eventName, subListener as EventListener)\n }\n\n private async emitInternal<TEventName extends keyof TEventData, TEventArgs extends TEventData[TEventName]>(\n eventName: TEventName,\n eventArgs: TEventArgs,\n filter?: TEventArgs,\n ) {\n if (isMetaEvent(eventName) && !Events.canEmitMetaEvents) {\n throw new TypeError('`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`')\n }\n\n this.logIfDebugEnabled('emit', eventName, eventArgs)\n\n const listeners = this.getListeners(eventName) ?? new Set()\n const filteredListeners = [...listeners.values()].filter((value) => (filter ? value.listener : true)).map((info) => info.listener)\n const anyListeners = assertEx(Events.anyMap.get(this))\n const staticListeners = [...filteredListeners]\n const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners]\n\n await resolvedPromise\n await Promise.all([\n ...staticListeners.map(async (listener) => {\n await this.safeCallListener(eventName, eventArgs, listener)\n }),\n ...staticAnyListeners.map(async (listener) => {\n if (anyListeners.has(listener)) {\n await this.safeCallAnyListener(eventName, eventArgs, listener)\n }\n }),\n ])\n }\n\n private async emitMetaEventInternal<TEventName extends keyof MetaEventData<TEventData>>(\n eventName: TEventName,\n eventArgs: MetaEventData<TEventData>[TEventName],\n ) {\n if (isMetaEvent(eventName) && !Events.canEmitMetaEvents) {\n throw new TypeError('`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`')\n }\n\n this.logIfDebugEnabled('emit', eventName, eventArgs)\n\n const listeners = this.getListeners(eventName) ?? new Set()\n const filteredListeners = [...listeners.values()].map((info) => info.listener)\n const anyListeners = assertEx(Events.anyMap.get(this))\n const staticListeners = [...filteredListeners]\n const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners]\n\n await resolvedPromise\n await Promise.all([\n ...staticListeners.map(async (listener) => {\n await this.safeCallListener(eventName, eventArgs, listener)\n }),\n ...staticAnyListeners.map(async (listener) => {\n if (anyListeners.has(listener)) {\n await this.safeCallAnyListener(eventName, eventArgs, listener)\n }\n }),\n ])\n }\n\n private getListeners<TEventName extends keyof TEventData>(eventName: TEventName) {\n const events = assertEx(Events.eventsMap.get(this))\n if (!events.has(eventName)) {\n return\n }\n\n return events.get(eventName)\n }\n\n private async safeCallAnyListener<TEventData extends EventData, TEventName extends keyof EventData>(\n eventName: TEventName,\n eventArgs: TEventData[TEventName],\n listener: EventAnyListener<TEventData[TEventName]>,\n ) {\n try {\n return await listener(eventName, eventArgs)\n } catch (ex) {\n handleError(ex, (error) => {\n this.logger?.error(`Listener[${String(eventName)}] Excepted: ${error.message}`)\n })\n }\n }\n\n private async safeCallListener<TEventData extends EventData, TEventName extends keyof EventData>(\n eventName: TEventName,\n eventArgs: TEventData[TEventName],\n listener: EventListener<TEventData[TEventName]>,\n ) {\n try {\n return await listener(eventArgs)\n } catch (ex) {\n handleError(ex, (error) => {\n this.logger?.error(`Listener[${String(eventName)}] Excepted: ${error.message}`)\n })\n }\n }\n}\n"],"mappings":"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","names":["eventName"]}
|
|
@@ -1,2 +1,262 @@
|
|
|
1
|
-
|
|
1
|
+
// src/Events/Events.ts
|
|
2
|
+
import { assertEx } from "@xylabs/assert";
|
|
3
|
+
import { forget } from "@xylabs/forget";
|
|
4
|
+
import { Base } from "@xyo-network/core";
|
|
5
|
+
import { handleError } from "@xyo-network/error";
|
|
6
|
+
var resolvedPromise = Promise.resolve();
|
|
7
|
+
var isMetaEvent = (eventName) => eventName === "listenerAdded" || eventName === "listenerRemoved";
|
|
8
|
+
var Events = class _Events extends Base {
|
|
9
|
+
static anyMap = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
static eventsMap = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
static canEmitMetaEvents = false;
|
|
12
|
+
static isGlobalDebugEnabled = false;
|
|
13
|
+
//this is here to be able to query the type, not use
|
|
14
|
+
eventData = {};
|
|
15
|
+
constructor(params = {}) {
|
|
16
|
+
const mutatedParams = { ...params };
|
|
17
|
+
if (mutatedParams.debug) {
|
|
18
|
+
mutatedParams.debug.logger = mutatedParams.debug.logger ?? ((type, debugName, eventName, eventData) => {
|
|
19
|
+
let eventDataString;
|
|
20
|
+
let eventNameString;
|
|
21
|
+
try {
|
|
22
|
+
eventDataString = JSON.stringify(eventData);
|
|
23
|
+
} catch {
|
|
24
|
+
eventDataString = `Object with the following keys failed to stringify: ${Object.keys(eventData ?? {}).join(",")}`;
|
|
25
|
+
}
|
|
26
|
+
if (typeof eventName === "symbol" || typeof eventName === "number") {
|
|
27
|
+
eventNameString = eventName.toString();
|
|
28
|
+
} else {
|
|
29
|
+
eventNameString = eventName;
|
|
30
|
+
}
|
|
31
|
+
const currentTime = /* @__PURE__ */ new Date();
|
|
32
|
+
const logTime = `${currentTime.getHours()}:${currentTime.getMinutes()}:${currentTime.getSeconds()}.${currentTime.getMilliseconds()}`;
|
|
33
|
+
this.logger.log(`[${logTime}][events:${type}][${debugName}] Event Name: ${eventNameString}
|
|
34
|
+
data: ${eventDataString}`);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
super(mutatedParams);
|
|
38
|
+
_Events.anyMap.set(this, /* @__PURE__ */ new Set());
|
|
39
|
+
_Events.eventsMap.set(this, /* @__PURE__ */ new Map());
|
|
40
|
+
}
|
|
41
|
+
static get isDebugEnabled() {
|
|
42
|
+
if (typeof globalThis.process?.env !== "object") {
|
|
43
|
+
return _Events.isGlobalDebugEnabled;
|
|
44
|
+
}
|
|
45
|
+
const { env } = globalThis.process ?? { env: {} };
|
|
46
|
+
return env.DEBUG === "events" || env.DEBUG === "*" || _Events.isGlobalDebugEnabled;
|
|
47
|
+
}
|
|
48
|
+
static set isDebugEnabled(newValue) {
|
|
49
|
+
_Events.isGlobalDebugEnabled = newValue;
|
|
50
|
+
}
|
|
51
|
+
get debug() {
|
|
52
|
+
return this.params.debug;
|
|
53
|
+
}
|
|
54
|
+
clearListeners(eventNames) {
|
|
55
|
+
const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames];
|
|
56
|
+
for (const eventName of eventNamesArray) {
|
|
57
|
+
this.logIfDebugEnabled("clear", eventName, void 0);
|
|
58
|
+
if (typeof eventName === "string" || typeof eventName === "symbol" || typeof eventName === "number") {
|
|
59
|
+
const set = this.getListeners(eventName);
|
|
60
|
+
if (set) {
|
|
61
|
+
set.clear();
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
_Events.anyMap.get(this)?.clear();
|
|
65
|
+
for (const [eventName2, listeners] of assertEx(_Events.eventsMap.get(this)).entries()) {
|
|
66
|
+
listeners.clear();
|
|
67
|
+
_Events.eventsMap.get(this)?.delete(eventName2);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async emit(eventName, eventArgs) {
|
|
73
|
+
await this.emitInternal(eventName, eventArgs);
|
|
74
|
+
}
|
|
75
|
+
async emitMetaEvent(eventName, eventArgs) {
|
|
76
|
+
if (isMetaEvent(eventName)) {
|
|
77
|
+
try {
|
|
78
|
+
_Events.canEmitMetaEvents = true;
|
|
79
|
+
await this.emitMetaEventInternal(eventName, eventArgs);
|
|
80
|
+
} finally {
|
|
81
|
+
_Events.canEmitMetaEvents = false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async emitSerial(eventName, eventArgs) {
|
|
86
|
+
if (isMetaEvent(eventName) && !_Events.canEmitMetaEvents) {
|
|
87
|
+
throw new TypeError("`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`");
|
|
88
|
+
}
|
|
89
|
+
const filterMatch = (args, filter) => {
|
|
90
|
+
if (filter) {
|
|
91
|
+
switch (typeof filter) {
|
|
92
|
+
case "object":
|
|
93
|
+
return Object.entries(args).reduce((prev, [key, value]) => filter[key] === value ? true : prev, false);
|
|
94
|
+
default:
|
|
95
|
+
return args === filter;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return true;
|
|
99
|
+
};
|
|
100
|
+
this.logIfDebugEnabled("emitSerial", eventName, eventArgs);
|
|
101
|
+
const listeners = this.getListeners(eventName) ?? /* @__PURE__ */ new Set();
|
|
102
|
+
const filteredListeners = [...listeners.values()].filter((value) => value.filter ? filterMatch(eventArgs, value.filter) : true).map((info) => info.listener);
|
|
103
|
+
const anyListeners = assertEx(_Events.anyMap.get(this));
|
|
104
|
+
const staticListeners = [...filteredListeners];
|
|
105
|
+
const staticAnyListeners = [...anyListeners];
|
|
106
|
+
await resolvedPromise;
|
|
107
|
+
for (const listener of staticListeners) {
|
|
108
|
+
await this.safeCallListener(eventName, eventArgs, listener);
|
|
109
|
+
}
|
|
110
|
+
for (const listener of staticAnyListeners) {
|
|
111
|
+
await this.safeCallAnyListener(eventName, eventArgs, listener);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//TODO: Make test for this
|
|
115
|
+
listenerCount(eventNames) {
|
|
116
|
+
const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames];
|
|
117
|
+
let count = 0;
|
|
118
|
+
for (const eventName of eventNamesArray) {
|
|
119
|
+
if (typeof eventName === "string") {
|
|
120
|
+
count += assertEx(_Events.anyMap.get(this)).size + (this.getListeners(eventName)?.size ?? 0);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
count += assertEx(_Events.anyMap.get(this)).size;
|
|
124
|
+
for (const value of assertEx(_Events.eventsMap.get(this)).values()) {
|
|
125
|
+
count += value.size;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return count;
|
|
129
|
+
}
|
|
130
|
+
logIfDebugEnabled(type, eventName, eventArgs) {
|
|
131
|
+
if (_Events.isDebugEnabled || this.debug?.enabled) {
|
|
132
|
+
this.debug?.logger?.(type, this.debug.name, eventName, eventArgs);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
off(eventNames, listener) {
|
|
136
|
+
const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames];
|
|
137
|
+
for (const eventName of eventNamesArray) {
|
|
138
|
+
const set = this.getListeners(eventName);
|
|
139
|
+
if (set) {
|
|
140
|
+
set.delete(listener);
|
|
141
|
+
if (set.size === 0) {
|
|
142
|
+
const events = _Events.eventsMap.get(this);
|
|
143
|
+
events?.delete(eventName);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
this.logIfDebugEnabled("unsubscribe", eventName, void 0);
|
|
147
|
+
if (!isMetaEvent(eventName)) {
|
|
148
|
+
forget(this.emitMetaEvent("listenerRemoved", { eventName, listener }));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
offAny(listener) {
|
|
153
|
+
this.logIfDebugEnabled("unsubscribeAny", void 0, void 0);
|
|
154
|
+
const typedMap = _Events.anyMap.get(this);
|
|
155
|
+
typedMap?.delete(listener);
|
|
156
|
+
forget(this.emitMetaEvent("listenerRemoved", { listener }));
|
|
157
|
+
}
|
|
158
|
+
on(eventNames, listener, filter) {
|
|
159
|
+
const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames];
|
|
160
|
+
for (const eventName of eventNamesArray) {
|
|
161
|
+
let set = this.getListeners(eventName);
|
|
162
|
+
if (!set) {
|
|
163
|
+
set = /* @__PURE__ */ new Set();
|
|
164
|
+
const events = _Events.eventsMap.get(this);
|
|
165
|
+
events?.set(eventName, set);
|
|
166
|
+
}
|
|
167
|
+
set.add({ filter, listener });
|
|
168
|
+
this.logIfDebugEnabled("subscribe", eventName, void 0);
|
|
169
|
+
if (!isMetaEvent(eventName)) {
|
|
170
|
+
forget(this.emitMetaEvent("listenerAdded", { eventName, listener }));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return this.off.bind(this, eventNames, listener);
|
|
174
|
+
}
|
|
175
|
+
onAny(listener) {
|
|
176
|
+
this.logIfDebugEnabled("subscribeAny", void 0, void 0);
|
|
177
|
+
_Events.anyMap.get(this)?.add(listener);
|
|
178
|
+
forget(this.emitMetaEvent("listenerAdded", { listener }));
|
|
179
|
+
return this.offAny.bind(this, listener);
|
|
180
|
+
}
|
|
181
|
+
once(eventName, listener) {
|
|
182
|
+
const subListener = async (args) => {
|
|
183
|
+
this.off(eventName, subListener);
|
|
184
|
+
await this.safeCallListener(eventName, args, listener);
|
|
185
|
+
};
|
|
186
|
+
this.on(eventName, subListener);
|
|
187
|
+
return this.off.bind(this, eventName, subListener);
|
|
188
|
+
}
|
|
189
|
+
async emitInternal(eventName, eventArgs, filter) {
|
|
190
|
+
if (isMetaEvent(eventName) && !_Events.canEmitMetaEvents) {
|
|
191
|
+
throw new TypeError("`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`");
|
|
192
|
+
}
|
|
193
|
+
this.logIfDebugEnabled("emit", eventName, eventArgs);
|
|
194
|
+
const listeners = this.getListeners(eventName) ?? /* @__PURE__ */ new Set();
|
|
195
|
+
const filteredListeners = [...listeners.values()].filter((value) => filter ? value.listener : true).map((info) => info.listener);
|
|
196
|
+
const anyListeners = assertEx(_Events.anyMap.get(this));
|
|
197
|
+
const staticListeners = [...filteredListeners];
|
|
198
|
+
const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners];
|
|
199
|
+
await resolvedPromise;
|
|
200
|
+
await Promise.all([
|
|
201
|
+
...staticListeners.map(async (listener) => {
|
|
202
|
+
await this.safeCallListener(eventName, eventArgs, listener);
|
|
203
|
+
}),
|
|
204
|
+
...staticAnyListeners.map(async (listener) => {
|
|
205
|
+
if (anyListeners.has(listener)) {
|
|
206
|
+
await this.safeCallAnyListener(eventName, eventArgs, listener);
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
]);
|
|
210
|
+
}
|
|
211
|
+
async emitMetaEventInternal(eventName, eventArgs) {
|
|
212
|
+
if (isMetaEvent(eventName) && !_Events.canEmitMetaEvents) {
|
|
213
|
+
throw new TypeError("`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`");
|
|
214
|
+
}
|
|
215
|
+
this.logIfDebugEnabled("emit", eventName, eventArgs);
|
|
216
|
+
const listeners = this.getListeners(eventName) ?? /* @__PURE__ */ new Set();
|
|
217
|
+
const filteredListeners = [...listeners.values()].map((info) => info.listener);
|
|
218
|
+
const anyListeners = assertEx(_Events.anyMap.get(this));
|
|
219
|
+
const staticListeners = [...filteredListeners];
|
|
220
|
+
const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners];
|
|
221
|
+
await resolvedPromise;
|
|
222
|
+
await Promise.all([
|
|
223
|
+
...staticListeners.map(async (listener) => {
|
|
224
|
+
await this.safeCallListener(eventName, eventArgs, listener);
|
|
225
|
+
}),
|
|
226
|
+
...staticAnyListeners.map(async (listener) => {
|
|
227
|
+
if (anyListeners.has(listener)) {
|
|
228
|
+
await this.safeCallAnyListener(eventName, eventArgs, listener);
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
]);
|
|
232
|
+
}
|
|
233
|
+
getListeners(eventName) {
|
|
234
|
+
const events = assertEx(_Events.eventsMap.get(this));
|
|
235
|
+
if (!events.has(eventName)) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
return events.get(eventName);
|
|
239
|
+
}
|
|
240
|
+
async safeCallAnyListener(eventName, eventArgs, listener) {
|
|
241
|
+
try {
|
|
242
|
+
return await listener(eventName, eventArgs);
|
|
243
|
+
} catch (ex) {
|
|
244
|
+
handleError(ex, (error) => {
|
|
245
|
+
this.logger?.error(`Listener[${String(eventName)}] Excepted: ${error.message}`);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async safeCallListener(eventName, eventArgs, listener) {
|
|
250
|
+
try {
|
|
251
|
+
return await listener(eventArgs);
|
|
252
|
+
} catch (ex) {
|
|
253
|
+
handleError(ex, (error) => {
|
|
254
|
+
this.logger?.error(`Listener[${String(eventName)}] Excepted: ${error.message}`);
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
export {
|
|
260
|
+
Events
|
|
261
|
+
};
|
|
2
262
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/Events/index.ts"],"sourcesContent":["export * from './Events'\n"],"mappings":"AAAA,cAAc;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/Events/Events.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { forget } from '@xylabs/forget'\nimport { Base, BaseParams } from '@xyo-network/core'\nimport { handleError } from '@xyo-network/error'\n\nimport { EventAnyListener, EventArgs, EventData, EventFunctions, EventListener, EventName } from '../model'\n\n/**\nEmittery can collect and log debug information.\n\nTo enable this feature set the `DEBUG` environment variable to `emittery` or `*`. Additionally, you can set the static `isDebugEnabled` variable to true on the Emittery class, or `myEmitter.debug.enabled` on an instance of it for debugging a single instance.\n\nSee API for more information on how debugging works.\n*/\nexport type DebugLogger = (type: string, debugName: string, eventName?: EventName, eventData?: EventArgs) => void\n\nexport type EventListenerInfo<TEventArgs extends EventArgs = EventArgs> = {\n filter?: TEventArgs\n listener: EventListener<TEventArgs>\n}\n\n/**\nConfigure debug options of an instance.\n*/\nexport type DebugOptions = {\n enabled?: boolean\n logger?: DebugLogger\n readonly name: string\n}\n\nconst resolvedPromise = Promise.resolve()\n\nexport type MetaEventData<TEventData extends EventData> = {\n listenerAdded: {\n eventName?: keyof TEventData\n listener: EventListener<TEventData[keyof TEventData]> | EventAnyListener<TEventData[keyof TEventData]>\n }\n listenerRemoved: {\n eventName?: keyof TEventData\n listener: EventListener<TEventData[keyof TEventData]> | EventAnyListener<TEventData[keyof TEventData]>\n }\n}\n\nconst isMetaEvent = (eventName: EventName) => eventName === 'listenerAdded' || eventName === 'listenerRemoved'\n\nexport type EventsParams = BaseParams<{ readonly debug?: DebugOptions }>\n\nexport class Events<TEventData extends EventData = EventData> extends Base<EventsParams> implements EventFunctions<TEventData> {\n protected static anyMap = new WeakMap<object, Set<EventAnyListener>>()\n protected static eventsMap = new WeakMap<object, Map<EventName, Set<EventListenerInfo>>>()\n\n private static canEmitMetaEvents = false\n private static isGlobalDebugEnabled = false\n\n //this is here to be able to query the type, not use\n eventData = {} as TEventData\n\n constructor(params: EventsParams = {}) {\n const mutatedParams = { ...params }\n if (mutatedParams.debug) {\n mutatedParams.debug.logger =\n mutatedParams.debug.logger ??\n ((type: string, debugName: string, eventName?: EventName, eventData?: EventArgs) => {\n let eventDataString: string\n let eventNameString: string | undefined\n try {\n eventDataString = JSON.stringify(eventData)\n } catch {\n eventDataString = `Object with the following keys failed to stringify: ${Object.keys(eventData ?? {}).join(',')}`\n }\n\n if (typeof eventName === 'symbol' || typeof eventName === 'number') {\n eventNameString = eventName.toString()\n } else {\n eventNameString = eventName\n }\n\n const currentTime = new Date()\n const logTime = `${currentTime.getHours()}:${currentTime.getMinutes()}:${currentTime.getSeconds()}.${currentTime.getMilliseconds()}`\n this.logger.log(`[${logTime}][events:${type}][${debugName}] Event Name: ${eventNameString}\\n\\tdata: ${eventDataString}`)\n })\n }\n super(mutatedParams)\n Events.anyMap.set(this, new Set<EventAnyListener>())\n Events.eventsMap.set(this, new Map<keyof TEventData, Set<EventListenerInfo>>())\n }\n\n static get isDebugEnabled() {\n // In a browser environment, `globalThis.process` can potentially reference a DOM Element with a `#process` ID,\n // so instead of just type checking `globalThis.process`, we need to make sure that `globalThis.process.env` exists.\n\n if (typeof globalThis.process?.env !== 'object') {\n return Events.isGlobalDebugEnabled\n }\n\n const { env } = globalThis.process ?? { env: {} }\n return env.DEBUG === 'events' || env.DEBUG === '*' || Events.isGlobalDebugEnabled\n }\n\n static set isDebugEnabled(newValue) {\n Events.isGlobalDebugEnabled = newValue\n }\n\n get debug() {\n return this.params.debug\n }\n\n clearListeners(eventNames: keyof TEventData | (keyof TEventData)[]) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n\n for (const eventName of eventNamesArray) {\n this.logIfDebugEnabled('clear', eventName, undefined)\n\n if (typeof eventName === 'string' || typeof eventName === 'symbol' || typeof eventName === 'number') {\n const set = this.getListeners(eventName)\n if (set) {\n set.clear()\n }\n } else {\n Events.anyMap.get(this)?.clear()\n\n for (const [eventName, listeners] of assertEx(Events.eventsMap.get(this)).entries()) {\n listeners.clear()\n Events.eventsMap.get(this)?.delete(eventName)\n }\n }\n }\n }\n\n async emit<TEventName extends keyof TEventData>(eventName: TEventName, eventArgs: TEventData[TEventName]) {\n await this.emitInternal(eventName, eventArgs)\n }\n\n async emitMetaEvent<TEventName extends keyof MetaEventData<TEventData>>(eventName: TEventName, eventArgs: MetaEventData<TEventData>[TEventName]) {\n if (isMetaEvent(eventName)) {\n try {\n Events.canEmitMetaEvents = true\n await this.emitMetaEventInternal(eventName, eventArgs)\n } finally {\n Events.canEmitMetaEvents = false\n }\n }\n }\n\n async emitSerial<TEventName extends keyof TEventData>(eventName: TEventName, eventArgs: TEventData[TEventName]) {\n if (isMetaEvent(eventName) && !Events.canEmitMetaEvents) {\n throw new TypeError('`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`')\n }\n\n const filterMatch = (args: TEventData[TEventName], filter: TEventData[TEventName]) => {\n if (filter) {\n switch (typeof filter) {\n case 'object':\n return Object.entries(args).reduce((prev, [key, value]) => ((filter as Record<PropertyKey, unknown>)[key] === value ? true : prev), false)\n default:\n return args === filter\n }\n }\n return true\n }\n\n this.logIfDebugEnabled('emitSerial', eventName, eventArgs)\n\n const listeners = this.getListeners(eventName) ?? new Set()\n const filteredListeners = [...listeners.values()]\n .filter((value) => (value.filter ? filterMatch(eventArgs, value.filter as TEventData[TEventName]) : true))\n .map((info) => info.listener)\n const anyListeners = assertEx(Events.anyMap.get(this))\n const staticListeners = [...filteredListeners]\n const staticAnyListeners = [...anyListeners]\n\n await resolvedPromise\n\n for (const listener of staticListeners) {\n await this.safeCallListener(eventName, eventArgs, listener)\n }\n\n for (const listener of staticAnyListeners) {\n await this.safeCallAnyListener(eventName, eventArgs, listener)\n }\n }\n\n //TODO: Make test for this\n listenerCount(eventNames?: keyof TEventData | (keyof TEventData)[]) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n let count = 0\n\n for (const eventName of eventNamesArray) {\n if (typeof eventName === 'string') {\n count += assertEx(Events.anyMap.get(this)).size + (this.getListeners(eventName)?.size ?? 0)\n\n continue\n }\n\n count += assertEx(Events.anyMap.get(this)).size\n\n for (const value of assertEx(Events.eventsMap.get(this)).values()) {\n count += value.size\n }\n }\n\n return count\n }\n\n logIfDebugEnabled<TEventName extends EventName>(type: string, eventName?: TEventName, eventArgs?: EventArgs) {\n if (Events.isDebugEnabled || this.debug?.enabled) {\n this.debug?.logger?.(type, this.debug.name, eventName, eventArgs)\n }\n }\n\n off<TEventName extends keyof TEventData, TEventListener = EventListener<TEventData[TEventName]>>(\n eventNames: TEventName | TEventName[],\n listener: TEventListener,\n ) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n for (const eventName of eventNamesArray) {\n const set = this.getListeners(eventName) as Set<TEventListener>\n if (set) {\n set.delete(listener)\n if (set.size === 0) {\n const events = Events.eventsMap.get(this)\n events?.delete(eventName)\n }\n }\n\n this.logIfDebugEnabled('unsubscribe', eventName, undefined)\n\n if (!isMetaEvent(eventName)) {\n forget(this.emitMetaEvent('listenerRemoved', { eventName, listener: listener as EventListener }))\n }\n }\n }\n\n offAny(listener: EventAnyListener) {\n this.logIfDebugEnabled('unsubscribeAny', undefined, undefined)\n\n const typedMap = Events.anyMap.get(this) as Set<EventAnyListener<TEventData[keyof TEventData]>>\n typedMap?.delete(listener)\n forget(this.emitMetaEvent('listenerRemoved', { listener: listener as EventAnyListener }))\n }\n\n on<TEventName extends keyof TEventData = keyof TEventData>(\n eventNames: TEventName | TEventName[],\n listener: EventListener<TEventData[TEventName]>,\n filter?: TEventData[TEventName],\n ) {\n const eventNamesArray = Array.isArray(eventNames) ? eventNames : [eventNames]\n for (const eventName of eventNamesArray) {\n let set = this.getListeners(eventName)\n if (!set) {\n set = new Set()\n const events = Events.eventsMap.get(this)\n events?.set(eventName, set)\n }\n\n set.add({ filter, listener: listener as EventListener })\n\n this.logIfDebugEnabled('subscribe', eventName, undefined)\n\n if (!isMetaEvent(eventName)) {\n forget(this.emitMetaEvent('listenerAdded', { eventName, listener: listener as EventListener }))\n }\n }\n\n return this.off.bind(this, eventNames, listener as EventListener)\n }\n\n onAny(listener: EventAnyListener) {\n this.logIfDebugEnabled('subscribeAny', undefined, undefined)\n\n Events.anyMap.get(this)?.add(listener as EventAnyListener)\n forget(this.emitMetaEvent('listenerAdded', { listener: listener as EventAnyListener }))\n return this.offAny.bind(this, listener as EventAnyListener)\n }\n\n once<TEventName extends keyof TEventData>(eventName: TEventName, listener: EventListener<TEventData[TEventName]>) {\n const subListener = async (args: TEventData[TEventName]) => {\n this.off(eventName, subListener)\n await this.safeCallListener(eventName, args, listener)\n }\n this.on(eventName, subListener)\n return this.off.bind(this, eventName, subListener as EventListener)\n }\n\n private async emitInternal<TEventName extends keyof TEventData, TEventArgs extends TEventData[TEventName]>(\n eventName: TEventName,\n eventArgs: TEventArgs,\n filter?: TEventArgs,\n ) {\n if (isMetaEvent(eventName) && !Events.canEmitMetaEvents) {\n throw new TypeError('`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`')\n }\n\n this.logIfDebugEnabled('emit', eventName, eventArgs)\n\n const listeners = this.getListeners(eventName) ?? new Set()\n const filteredListeners = [...listeners.values()].filter((value) => (filter ? value.listener : true)).map((info) => info.listener)\n const anyListeners = assertEx(Events.anyMap.get(this))\n const staticListeners = [...filteredListeners]\n const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners]\n\n await resolvedPromise\n await Promise.all([\n ...staticListeners.map(async (listener) => {\n await this.safeCallListener(eventName, eventArgs, listener)\n }),\n ...staticAnyListeners.map(async (listener) => {\n if (anyListeners.has(listener)) {\n await this.safeCallAnyListener(eventName, eventArgs, listener)\n }\n }),\n ])\n }\n\n private async emitMetaEventInternal<TEventName extends keyof MetaEventData<TEventData>>(\n eventName: TEventName,\n eventArgs: MetaEventData<TEventData>[TEventName],\n ) {\n if (isMetaEvent(eventName) && !Events.canEmitMetaEvents) {\n throw new TypeError('`eventName` cannot be meta event `listenerAdded` or `listenerRemoved`')\n }\n\n this.logIfDebugEnabled('emit', eventName, eventArgs)\n\n const listeners = this.getListeners(eventName) ?? new Set()\n const filteredListeners = [...listeners.values()].map((info) => info.listener)\n const anyListeners = assertEx(Events.anyMap.get(this))\n const staticListeners = [...filteredListeners]\n const staticAnyListeners = isMetaEvent(eventName) ? [] : [...anyListeners]\n\n await resolvedPromise\n await Promise.all([\n ...staticListeners.map(async (listener) => {\n await this.safeCallListener(eventName, eventArgs, listener)\n }),\n ...staticAnyListeners.map(async (listener) => {\n if (anyListeners.has(listener)) {\n await this.safeCallAnyListener(eventName, eventArgs, listener)\n }\n }),\n ])\n }\n\n private getListeners<TEventName extends keyof TEventData>(eventName: TEventName) {\n const events = assertEx(Events.eventsMap.get(this))\n if (!events.has(eventName)) {\n return\n }\n\n return events.get(eventName)\n }\n\n private async safeCallAnyListener<TEventData extends EventData, TEventName extends keyof EventData>(\n eventName: TEventName,\n eventArgs: TEventData[TEventName],\n listener: EventAnyListener<TEventData[TEventName]>,\n ) {\n try {\n return await listener(eventName, eventArgs)\n } catch (ex) {\n handleError(ex, (error) => {\n this.logger?.error(`Listener[${String(eventName)}] Excepted: ${error.message}`)\n })\n }\n }\n\n private async safeCallListener<TEventData extends EventData, TEventName extends keyof EventData>(\n eventName: TEventName,\n eventArgs: TEventData[TEventName],\n listener: EventListener<TEventData[TEventName]>,\n ) {\n try {\n return await listener(eventArgs)\n } catch (ex) {\n handleError(ex, (error) => {\n this.logger?.error(`Listener[${String(eventName)}] Excepted: ${error.message}`)\n })\n }\n }\n}\n"],"mappings":"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","names":["eventName"]}
|