hookified 1.12.1 → 1.12.2

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.
@@ -1 +1,595 @@
1
- "use strict";var l=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var m=(o,e)=>{for(var t in e)l(o,t,{get:e[t],enumerable:!0})},d=(o,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of g(e))!p.call(o,s)&&s!==t&&l(o,s,{get:()=>e[s],enumerable:!(r=c(e,s))||r.enumerable});return o};var f=o=>d(l({},"__esModule",{value:!0}),o);var u={};m(u,{Eventified:()=>i,Hookified:()=>h});module.exports=f(u);var i=class{_eventListeners;_maxListeners;_logger;_throwOnEmitError=!1;constructor(e){this._eventListeners=new Map,this._maxListeners=100,this._logger=e?.logger,e?.throwOnEmitError!==void 0&&(this._throwOnEmitError=e.throwOnEmitError)}get logger(){return this._logger}set logger(e){this._logger=e}get throwOnEmitError(){return this._throwOnEmitError}set throwOnEmitError(e){this._throwOnEmitError=e}once(e,t){let r=(...s)=>{this.off(e,r),t(...s)};return this.on(e,r),this}listenerCount(e){if(e===void 0)return this.getAllListeners().length;let t=this._eventListeners.get(e);return t?t.length:0}eventNames(){return[...this._eventListeners.keys()]}rawListeners(e){return e===void 0?this.getAllListeners():this._eventListeners.get(e)??[]}prependListener(e,t){let r=this._eventListeners.get(e)??[];return r.unshift(t),this._eventListeners.set(e,r),this}prependOnceListener(e,t){let r=(...s)=>{this.off(e,r),t(...s)};return this.prependListener(e,r),this}maxListeners(){return this._maxListeners}addListener(e,t){return this.on(e,t),this}on(e,t){this._eventListeners.has(e)||this._eventListeners.set(e,[]);let r=this._eventListeners.get(e);return r&&(r.length>=this._maxListeners&&console.warn(`MaxListenersExceededWarning: Possible event memory leak detected. ${r.length+1} ${e} listeners added. Use setMaxListeners() to increase limit.`),r.push(t)),this}removeListener(e,t){return this.off(e,t),this}off(e,t){let r=this._eventListeners.get(e)??[],s=r.indexOf(t);return s!==-1&&r.splice(s,1),r.length===0&&this._eventListeners.delete(e),this}emit(e,...t){let r=!1,s=this._eventListeners.get(e);if(s&&s.length>0)for(let n of s)n(...t),r=!0;if(e==="error"){let n=t[0]instanceof Error?t[0]:new Error(`${t[0]}`);if(this._throwOnEmitError&&!r)throw n}return r}listeners(e){return this._eventListeners.get(e)??[]}removeAllListeners(e){return e!==void 0?this._eventListeners.delete(e):this._eventListeners.clear(),this}setMaxListeners(e){this._maxListeners=e;for(let t of this._eventListeners.values())t.length>e&&t.splice(e)}getAllListeners(){let e=[];for(let t of this._eventListeners.values())e=[...e,...t];return e}};var h=class extends i{_hooks;_throwHookErrors=!1;_enforceBeforeAfter=!1;_deprecatedHooks;_allowDeprecated=!0;constructor(e){super({logger:e?.logger}),this._hooks=new Map,this._deprecatedHooks=e?.deprecatedHooks?new Map(e.deprecatedHooks):new Map,e?.throwHookErrors!==void 0&&(this._throwHookErrors=e.throwHookErrors),e?.enforceBeforeAfter!==void 0&&(this._enforceBeforeAfter=e.enforceBeforeAfter),e?.allowDeprecated!==void 0&&(this._allowDeprecated=e.allowDeprecated)}get hooks(){return this._hooks}get throwHookErrors(){return this._throwHookErrors}set throwHookErrors(e){this._throwHookErrors=e}get enforceBeforeAfter(){return this._enforceBeforeAfter}set enforceBeforeAfter(e){this._enforceBeforeAfter=e}get deprecatedHooks(){return this._deprecatedHooks}set deprecatedHooks(e){this._deprecatedHooks=e}get allowDeprecated(){return this._allowDeprecated}set allowDeprecated(e){this._allowDeprecated=e}validateHookName(e){if(this._enforceBeforeAfter){let t=e.trim().toLocaleLowerCase();if(!t.startsWith("before")&&!t.startsWith("after"))throw new Error(`Hook event "${e}" must start with "before" or "after" when enforceBeforeAfter is enabled`)}}checkDeprecatedHook(e){if(this._deprecatedHooks.has(e)){let t=this._deprecatedHooks.get(e),r=`Hook "${e}" is deprecated${t?`: ${t}`:""}`;return this.emit("warn",{hook:e,message:r}),this.logger?.warn&&this.logger.warn(r),this._allowDeprecated}return!0}onHook(e,t){if(this.validateHookName(e),!this.checkDeprecatedHook(e))return;let r=this._hooks.get(e);r?r.push(t):this._hooks.set(e,[t])}onHookEntry(e){this.onHook(e.event,e.handler)}addHook(e,t){this.onHook(e,t)}onHooks(e){for(let t of e)this.onHook(t.event,t.handler)}prependHook(e,t){if(this.validateHookName(e),!this.checkDeprecatedHook(e))return;let r=this._hooks.get(e);r?r.unshift(t):this._hooks.set(e,[t])}prependOnceHook(e,t){if(this.validateHookName(e),!this.checkDeprecatedHook(e))return;let r=async(...s)=>(this.removeHook(e,r),t(...s));this.prependHook(e,r)}onceHook(e,t){if(this.validateHookName(e),!this.checkDeprecatedHook(e))return;let r=async(...s)=>(this.removeHook(e,r),t(...s));this.onHook(e,r)}removeHook(e,t){if(this.validateHookName(e),!this.checkDeprecatedHook(e))return;let r=this._hooks.get(e);if(r){let s=r.indexOf(t);s!==-1&&r.splice(s,1)}}removeHooks(e){for(let t of e)this.removeHook(t.event,t.handler)}async hook(e,...t){if(this.validateHookName(e),!this.checkDeprecatedHook(e))return;let r=this._hooks.get(e);if(r)for(let s of r)try{await s(...t)}catch(n){let a=`${e}: ${n.message}`;if(this.emit("error",new Error(a)),this.logger&&this.logger.error(a),this._throwHookErrors)throw new Error(a)}}async beforeHook(e,...t){await this.hook(`before:${e}`,...t)}async afterHook(e,...t){await this.hook(`after:${e}`,...t)}async callHook(e,...t){await this.hook(e,...t)}getHooks(e){if(this.validateHookName(e),!!this.checkDeprecatedHook(e))return this._hooks.get(e)}clearHooks(){this._hooks.clear()}};0&&(module.exports={Eventified,Hookified});
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Eventified: () => Eventified,
24
+ Hookified: () => Hookified
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/eventified.ts
29
+ var Eventified = class {
30
+ _eventListeners;
31
+ _maxListeners;
32
+ _logger;
33
+ _throwOnEmitError = false;
34
+ constructor(options) {
35
+ this._eventListeners = /* @__PURE__ */ new Map();
36
+ this._maxListeners = 100;
37
+ this._logger = options?.logger;
38
+ if (options?.throwOnEmitError !== void 0) {
39
+ this._throwOnEmitError = options.throwOnEmitError;
40
+ }
41
+ }
42
+ /**
43
+ * Gets the logger
44
+ * @returns {Logger}
45
+ */
46
+ get logger() {
47
+ return this._logger;
48
+ }
49
+ /**
50
+ * Sets the logger
51
+ * @param {Logger} logger
52
+ */
53
+ set logger(logger) {
54
+ this._logger = logger;
55
+ }
56
+ /**
57
+ * Gets whether an error should be thrown when an emit throws an error. Default is false and only emits an error event.
58
+ * @returns {boolean}
59
+ */
60
+ get throwOnEmitError() {
61
+ return this._throwOnEmitError;
62
+ }
63
+ /**
64
+ * Sets whether an error should be thrown when an emit throws an error. Default is false and only emits an error event.
65
+ * @param {boolean} value
66
+ */
67
+ set throwOnEmitError(value) {
68
+ this._throwOnEmitError = value;
69
+ }
70
+ /**
71
+ * Adds a handler function for a specific event that will run only once
72
+ * @param {string | symbol} eventName
73
+ * @param {EventListener} listener
74
+ * @returns {IEventEmitter} returns the instance of the class for chaining
75
+ */
76
+ once(eventName, listener) {
77
+ const onceListener = (...arguments_) => {
78
+ this.off(eventName, onceListener);
79
+ listener(...arguments_);
80
+ };
81
+ this.on(eventName, onceListener);
82
+ return this;
83
+ }
84
+ /**
85
+ * Gets the number of listeners for a specific event. If no event is provided, it returns the total number of listeners
86
+ * @param {string} eventName The event name. Not required
87
+ * @returns {number} The number of listeners
88
+ */
89
+ listenerCount(eventName) {
90
+ if (eventName === void 0) {
91
+ return this.getAllListeners().length;
92
+ }
93
+ const listeners = this._eventListeners.get(eventName);
94
+ return listeners ? listeners.length : 0;
95
+ }
96
+ /**
97
+ * Gets an array of event names
98
+ * @returns {Array<string | symbol>} An array of event names
99
+ */
100
+ eventNames() {
101
+ return [...this._eventListeners.keys()];
102
+ }
103
+ /**
104
+ * Gets an array of listeners for a specific event. If no event is provided, it returns all listeners
105
+ * @param {string} [event] (Optional) The event name
106
+ * @returns {EventListener[]} An array of listeners
107
+ */
108
+ rawListeners(event) {
109
+ if (event === void 0) {
110
+ return this.getAllListeners();
111
+ }
112
+ return this._eventListeners.get(event) ?? [];
113
+ }
114
+ /**
115
+ * Prepends a listener to the beginning of the listeners array for the specified event
116
+ * @param {string | symbol} eventName
117
+ * @param {EventListener} listener
118
+ * @returns {IEventEmitter} returns the instance of the class for chaining
119
+ */
120
+ prependListener(eventName, listener) {
121
+ const listeners = this._eventListeners.get(eventName) ?? [];
122
+ listeners.unshift(listener);
123
+ this._eventListeners.set(eventName, listeners);
124
+ return this;
125
+ }
126
+ /**
127
+ * Prepends a one-time listener to the beginning of the listeners array for the specified event
128
+ * @param {string | symbol} eventName
129
+ * @param {EventListener} listener
130
+ * @returns {IEventEmitter} returns the instance of the class for chaining
131
+ */
132
+ prependOnceListener(eventName, listener) {
133
+ const onceListener = (...arguments_) => {
134
+ this.off(eventName, onceListener);
135
+ listener(...arguments_);
136
+ };
137
+ this.prependListener(eventName, onceListener);
138
+ return this;
139
+ }
140
+ /**
141
+ * Gets the maximum number of listeners that can be added for a single event
142
+ * @returns {number} The maximum number of listeners
143
+ */
144
+ maxListeners() {
145
+ return this._maxListeners;
146
+ }
147
+ /**
148
+ * Adds a listener for a specific event. It is an alias for the on() method
149
+ * @param {string | symbol} event
150
+ * @param {EventListener} listener
151
+ * @returns {IEventEmitter} returns the instance of the class for chaining
152
+ */
153
+ addListener(event, listener) {
154
+ this.on(event, listener);
155
+ return this;
156
+ }
157
+ /**
158
+ * Adds a listener for a specific event
159
+ * @param {string | symbol} event
160
+ * @param {EventListener} listener
161
+ * @returns {IEventEmitter} returns the instance of the class for chaining
162
+ */
163
+ on(event, listener) {
164
+ if (!this._eventListeners.has(event)) {
165
+ this._eventListeners.set(event, []);
166
+ }
167
+ const listeners = this._eventListeners.get(event);
168
+ if (listeners) {
169
+ if (listeners.length >= this._maxListeners) {
170
+ console.warn(
171
+ `MaxListenersExceededWarning: Possible event memory leak detected. ${listeners.length + 1} ${event} listeners added. Use setMaxListeners() to increase limit.`
172
+ );
173
+ }
174
+ listeners.push(listener);
175
+ }
176
+ return this;
177
+ }
178
+ /**
179
+ * Removes a listener for a specific event. It is an alias for the off() method
180
+ * @param {string | symbol} event
181
+ * @param {EventListener} listener
182
+ * @returns {IEventEmitter} returns the instance of the class for chaining
183
+ */
184
+ removeListener(event, listener) {
185
+ this.off(event, listener);
186
+ return this;
187
+ }
188
+ /**
189
+ * Removes a listener for a specific event
190
+ * @param {string | symbol} event
191
+ * @param {EventListener} listener
192
+ * @returns {IEventEmitter} returns the instance of the class for chaining
193
+ */
194
+ off(event, listener) {
195
+ const listeners = this._eventListeners.get(event) ?? [];
196
+ const index = listeners.indexOf(listener);
197
+ if (index !== -1) {
198
+ listeners.splice(index, 1);
199
+ }
200
+ if (listeners.length === 0) {
201
+ this._eventListeners.delete(event);
202
+ }
203
+ return this;
204
+ }
205
+ /**
206
+ * Calls all listeners for a specific event
207
+ * @param {string | symbol} event
208
+ * @param arguments_ The arguments to pass to the listeners
209
+ * @returns {boolean} Returns true if the event had listeners, false otherwise
210
+ */
211
+ emit(event, ...arguments_) {
212
+ let result = false;
213
+ const listeners = this._eventListeners.get(event);
214
+ if (listeners && listeners.length > 0) {
215
+ for (const listener of listeners) {
216
+ listener(...arguments_);
217
+ result = true;
218
+ }
219
+ }
220
+ if (event === "error") {
221
+ const error = arguments_[0] instanceof Error ? arguments_[0] : new Error(`${arguments_[0]}`);
222
+ if (this._throwOnEmitError && !result) {
223
+ throw error;
224
+ }
225
+ }
226
+ return result;
227
+ }
228
+ /**
229
+ * Gets all listeners for a specific event. If no event is provided, it returns all listeners
230
+ * @param {string} [event] (Optional) The event name
231
+ * @returns {EventListener[]} An array of listeners
232
+ */
233
+ listeners(event) {
234
+ return this._eventListeners.get(event) ?? [];
235
+ }
236
+ /**
237
+ * Removes all listeners for a specific event. If no event is provided, it removes all listeners
238
+ * @param {string} [event] (Optional) The event name
239
+ * @returns {IEventEmitter} returns the instance of the class for chaining
240
+ */
241
+ removeAllListeners(event) {
242
+ if (event !== void 0) {
243
+ this._eventListeners.delete(event);
244
+ } else {
245
+ this._eventListeners.clear();
246
+ }
247
+ return this;
248
+ }
249
+ /**
250
+ * Sets the maximum number of listeners that can be added for a single event
251
+ * @param {number} n The maximum number of listeners
252
+ * @returns {void}
253
+ */
254
+ setMaxListeners(n) {
255
+ this._maxListeners = n;
256
+ for (const listeners of this._eventListeners.values()) {
257
+ if (listeners.length > n) {
258
+ listeners.splice(n);
259
+ }
260
+ }
261
+ }
262
+ /**
263
+ * Gets all listeners
264
+ * @returns {EventListener[]} An array of listeners
265
+ */
266
+ getAllListeners() {
267
+ let result = [];
268
+ for (const listeners of this._eventListeners.values()) {
269
+ result = [...result, ...listeners];
270
+ }
271
+ return result;
272
+ }
273
+ };
274
+
275
+ // src/index.ts
276
+ var Hookified = class extends Eventified {
277
+ _hooks;
278
+ _throwHookErrors = false;
279
+ _enforceBeforeAfter = false;
280
+ _deprecatedHooks;
281
+ _allowDeprecated = true;
282
+ constructor(options) {
283
+ super({ logger: options?.logger });
284
+ this._hooks = /* @__PURE__ */ new Map();
285
+ this._deprecatedHooks = options?.deprecatedHooks ? new Map(options.deprecatedHooks) : /* @__PURE__ */ new Map();
286
+ if (options?.throwHookErrors !== void 0) {
287
+ this._throwHookErrors = options.throwHookErrors;
288
+ }
289
+ if (options?.enforceBeforeAfter !== void 0) {
290
+ this._enforceBeforeAfter = options.enforceBeforeAfter;
291
+ }
292
+ if (options?.allowDeprecated !== void 0) {
293
+ this._allowDeprecated = options.allowDeprecated;
294
+ }
295
+ }
296
+ /**
297
+ * Gets all hooks
298
+ * @returns {Map<string, Hook[]>}
299
+ */
300
+ get hooks() {
301
+ return this._hooks;
302
+ }
303
+ /**
304
+ * Gets whether an error should be thrown when a hook throws an error. Default is false and only emits an error event.
305
+ * @returns {boolean}
306
+ */
307
+ get throwHookErrors() {
308
+ return this._throwHookErrors;
309
+ }
310
+ /**
311
+ * Sets whether an error should be thrown when a hook throws an error. Default is false and only emits an error event.
312
+ * @param {boolean} value
313
+ */
314
+ set throwHookErrors(value) {
315
+ this._throwHookErrors = value;
316
+ }
317
+ /**
318
+ * Gets whether to enforce that all hook names start with 'before' or 'after'. Default is false.
319
+ * @returns {boolean}
320
+ * @default false
321
+ */
322
+ get enforceBeforeAfter() {
323
+ return this._enforceBeforeAfter;
324
+ }
325
+ /**
326
+ * Sets whether to enforce that all hook names start with 'before' or 'after'. Default is false.
327
+ * @param {boolean} value
328
+ */
329
+ set enforceBeforeAfter(value) {
330
+ this._enforceBeforeAfter = value;
331
+ }
332
+ /**
333
+ * Gets the map of deprecated hook names to deprecation messages.
334
+ * @returns {Map<string, string>}
335
+ */
336
+ get deprecatedHooks() {
337
+ return this._deprecatedHooks;
338
+ }
339
+ /**
340
+ * Sets the map of deprecated hook names to deprecation messages.
341
+ * @param {Map<string, string>} value
342
+ */
343
+ set deprecatedHooks(value) {
344
+ this._deprecatedHooks = value;
345
+ }
346
+ /**
347
+ * Gets whether deprecated hooks are allowed to be registered and executed. Default is true.
348
+ * @returns {boolean}
349
+ */
350
+ get allowDeprecated() {
351
+ return this._allowDeprecated;
352
+ }
353
+ /**
354
+ * Sets whether deprecated hooks are allowed to be registered and executed. Default is true.
355
+ * @param {boolean} value
356
+ */
357
+ set allowDeprecated(value) {
358
+ this._allowDeprecated = value;
359
+ }
360
+ /**
361
+ * Validates hook event name if enforceBeforeAfter is enabled
362
+ * @param {string} event - The event name to validate
363
+ * @throws {Error} If enforceBeforeAfter is true and event doesn't start with 'before' or 'after'
364
+ */
365
+ validateHookName(event) {
366
+ if (this._enforceBeforeAfter) {
367
+ const eventValue = event.trim().toLocaleLowerCase();
368
+ if (!eventValue.startsWith("before") && !eventValue.startsWith("after")) {
369
+ throw new Error(
370
+ `Hook event "${event}" must start with "before" or "after" when enforceBeforeAfter is enabled`
371
+ );
372
+ }
373
+ }
374
+ }
375
+ /**
376
+ * Checks if a hook is deprecated and emits a warning if it is
377
+ * @param {string} event - The event name to check
378
+ * @returns {boolean} - Returns true if the hook should proceed, false if it should be blocked
379
+ */
380
+ checkDeprecatedHook(event) {
381
+ if (this._deprecatedHooks.has(event)) {
382
+ const message = this._deprecatedHooks.get(event);
383
+ const warningMessage = `Hook "${event}" is deprecated${message ? `: ${message}` : ""}`;
384
+ this.emit("warn", { hook: event, message: warningMessage });
385
+ if (this.logger?.warn) {
386
+ this.logger.warn(warningMessage);
387
+ }
388
+ return this._allowDeprecated;
389
+ }
390
+ return true;
391
+ }
392
+ /**
393
+ * Adds a handler function for a specific event
394
+ * @param {string} event
395
+ * @param {Hook} handler - this can be async or sync
396
+ * @returns {void}
397
+ */
398
+ onHook(event, handler) {
399
+ this.validateHookName(event);
400
+ if (!this.checkDeprecatedHook(event)) {
401
+ return;
402
+ }
403
+ const eventHandlers = this._hooks.get(event);
404
+ if (eventHandlers) {
405
+ eventHandlers.push(handler);
406
+ } else {
407
+ this._hooks.set(event, [handler]);
408
+ }
409
+ }
410
+ /**
411
+ * Adds a handler function for a specific event that runs before all other handlers
412
+ * @param {HookEntry} hookEntry
413
+ * @returns {void}
414
+ */
415
+ onHookEntry(hookEntry) {
416
+ this.onHook(hookEntry.event, hookEntry.handler);
417
+ }
418
+ /**
419
+ * Alias for onHook. This is provided for compatibility with other libraries that use the `addHook` method.
420
+ * @param {string} event
421
+ * @param {Hook} handler - this can be async or sync
422
+ * @returns {void}
423
+ */
424
+ addHook(event, handler) {
425
+ this.onHook(event, handler);
426
+ }
427
+ /**
428
+ * Adds a handler function for a specific event
429
+ * @param {Array<HookEntry>} hooks
430
+ * @returns {void}
431
+ */
432
+ onHooks(hooks) {
433
+ for (const hook of hooks) {
434
+ this.onHook(hook.event, hook.handler);
435
+ }
436
+ }
437
+ /**
438
+ * Adds a handler function for a specific event that runs before all other handlers
439
+ * @param {string} event
440
+ * @param {Hook} handler - this can be async or sync
441
+ * @returns {void}
442
+ */
443
+ prependHook(event, handler) {
444
+ this.validateHookName(event);
445
+ if (!this.checkDeprecatedHook(event)) {
446
+ return;
447
+ }
448
+ const eventHandlers = this._hooks.get(event);
449
+ if (eventHandlers) {
450
+ eventHandlers.unshift(handler);
451
+ } else {
452
+ this._hooks.set(event, [handler]);
453
+ }
454
+ }
455
+ /**
456
+ * Adds a handler that only executes once for a specific event before all other handlers
457
+ * @param event
458
+ * @param handler
459
+ */
460
+ prependOnceHook(event, handler) {
461
+ this.validateHookName(event);
462
+ if (!this.checkDeprecatedHook(event)) {
463
+ return;
464
+ }
465
+ const hook = async (...arguments_) => {
466
+ this.removeHook(event, hook);
467
+ return handler(...arguments_);
468
+ };
469
+ this.prependHook(event, hook);
470
+ }
471
+ /**
472
+ * Adds a handler that only executes once for a specific event
473
+ * @param event
474
+ * @param handler
475
+ */
476
+ onceHook(event, handler) {
477
+ this.validateHookName(event);
478
+ if (!this.checkDeprecatedHook(event)) {
479
+ return;
480
+ }
481
+ const hook = async (...arguments_) => {
482
+ this.removeHook(event, hook);
483
+ return handler(...arguments_);
484
+ };
485
+ this.onHook(event, hook);
486
+ }
487
+ /**
488
+ * Removes a handler function for a specific event
489
+ * @param {string} event
490
+ * @param {Hook} handler
491
+ * @returns {void}
492
+ */
493
+ removeHook(event, handler) {
494
+ this.validateHookName(event);
495
+ if (!this.checkDeprecatedHook(event)) {
496
+ return;
497
+ }
498
+ const eventHandlers = this._hooks.get(event);
499
+ if (eventHandlers) {
500
+ const index = eventHandlers.indexOf(handler);
501
+ if (index !== -1) {
502
+ eventHandlers.splice(index, 1);
503
+ }
504
+ }
505
+ }
506
+ /**
507
+ * Removes all handlers for a specific event
508
+ * @param {Array<HookEntry>} hooks
509
+ * @returns {void}
510
+ */
511
+ removeHooks(hooks) {
512
+ for (const hook of hooks) {
513
+ this.removeHook(hook.event, hook.handler);
514
+ }
515
+ }
516
+ /**
517
+ * Calls all handlers for a specific event
518
+ * @param {string} event
519
+ * @param {T[]} arguments_
520
+ * @returns {Promise<void>}
521
+ */
522
+ async hook(event, ...arguments_) {
523
+ this.validateHookName(event);
524
+ if (!this.checkDeprecatedHook(event)) {
525
+ return;
526
+ }
527
+ const eventHandlers = this._hooks.get(event);
528
+ if (eventHandlers) {
529
+ for (const handler of eventHandlers) {
530
+ try {
531
+ await handler(...arguments_);
532
+ } catch (error) {
533
+ const message = `${event}: ${error.message}`;
534
+ this.emit("error", new Error(message));
535
+ if (this.logger) {
536
+ this.logger.error(message);
537
+ }
538
+ if (this._throwHookErrors) {
539
+ throw new Error(message);
540
+ }
541
+ }
542
+ }
543
+ }
544
+ }
545
+ /**
546
+ * Prepends the word `before` to your hook. Example is event is `test`, the before hook is `before:test`.
547
+ * @param {string} event - The event name
548
+ * @param {T[]} arguments_ - The arguments to pass to the hook
549
+ */
550
+ async beforeHook(event, ...arguments_) {
551
+ await this.hook(`before:${event}`, ...arguments_);
552
+ }
553
+ /**
554
+ * Prepends the word `after` to your hook. Example is event is `test`, the after hook is `after:test`.
555
+ * @param {string} event - The event name
556
+ * @param {T[]} arguments_ - The arguments to pass to the hook
557
+ */
558
+ async afterHook(event, ...arguments_) {
559
+ await this.hook(`after:${event}`, ...arguments_);
560
+ }
561
+ /**
562
+ * Calls all handlers for a specific event. This is an alias for `hook` and is provided for
563
+ * compatibility with other libraries that use the `callHook` method.
564
+ * @param {string} event
565
+ * @param {T[]} arguments_
566
+ * @returns {Promise<void>}
567
+ */
568
+ async callHook(event, ...arguments_) {
569
+ await this.hook(event, ...arguments_);
570
+ }
571
+ /**
572
+ * Gets all hooks for a specific event
573
+ * @param {string} event
574
+ * @returns {Hook[]}
575
+ */
576
+ getHooks(event) {
577
+ this.validateHookName(event);
578
+ if (!this.checkDeprecatedHook(event)) {
579
+ return void 0;
580
+ }
581
+ return this._hooks.get(event);
582
+ }
583
+ /**
584
+ * Removes all hooks
585
+ * @returns {void}
586
+ */
587
+ clearHooks() {
588
+ this._hooks.clear();
589
+ }
590
+ };
591
+ // Annotate the CommonJS export names for ESM import in node:
592
+ 0 && (module.exports = {
593
+ Eventified,
594
+ Hookified
595
+ });