hookified 1.15.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,16 +8,16 @@ type Logger = {
8
8
  };
9
9
  type EventEmitterOptions = {
10
10
  /**
11
- * Logger instance for logging errors.
11
+ * Logger instance for logging events.
12
12
  */
13
- logger?: Logger;
13
+ eventLogger?: Logger;
14
14
  /**
15
15
  * Whether to throw an error when emit 'error' and there are no listeners. Default is false and only emits an error event.
16
16
  */
17
17
  throwOnEmitError?: boolean;
18
18
  /**
19
19
  * Whether to throw on 'error' when there are no listeners. This is the standard functionality in EventEmitter
20
- * @default false - in v2 this will be set to true by default
20
+ * @default true
21
21
  */
22
22
  throwOnEmptyListeners?: boolean;
23
23
  };
@@ -166,8 +166,12 @@ type IEventEmitter = {
166
166
  prependOnceListener(eventName: string | symbol, listener: (...arguments_: any[]) => void): IEventEmitter;
167
167
  };
168
168
  type EventListener = (...arguments_: any[]) => void;
169
- type Hook = (...arguments_: any[]) => Promise<void> | void;
170
- type HookEntry = {
169
+ type HookFn = (...arguments_: any[]) => Promise<void> | void;
170
+ interface IHook {
171
+ /**
172
+ * Unique identifier for the hook. Auto-generated via crypto.randomUUID() if not provided.
173
+ */
174
+ id?: string;
171
175
  /**
172
176
  * The event name for the hook
173
177
  */
@@ -175,14 +179,64 @@ type HookEntry = {
175
179
  /**
176
180
  * The handler function for the hook
177
181
  */
178
- handler: Hook;
182
+ handler: HookFn;
183
+ }
184
+ type WaterfallHookResult = {
185
+ /**
186
+ * The hook function that produced this result
187
+ */
188
+ hook: WaterfallHookFn;
189
+ /**
190
+ * The value returned by the hook
191
+ */
192
+ result: any;
179
193
  };
180
- type HookifiedOptions = {
194
+ type WaterfallHookContext = {
181
195
  /**
182
- * Whether an error should be thrown when a hook throws an error. Default is false and only emits an error event.
183
- * @deprecated - this will be deprecated in version 2. Please use throwOnHookError.
196
+ * The original arguments passed to the waterfall execution, before any hooks processed them.
197
+ */
198
+ initialArgs: any;
199
+ /**
200
+ * Array of results from previous hooks in execution order, each containing the hook and its result.
201
+ * Empty for the first hook.
202
+ */
203
+ results: WaterfallHookResult[];
204
+ };
205
+ type WaterfallHookFn = (context: WaterfallHookContext) => Promise<any> | any;
206
+ interface IWaterfallHook extends IHook {
207
+ /**
208
+ * Array of hook functions that are called sequentially.
209
+ * Each hook receives a WaterfallHookContext with initialArgs and results.
210
+ */
211
+ hooks: WaterfallHookFn[];
212
+ /**
213
+ * Adds a hook function to the end of the waterfall chain
214
+ */
215
+ addHook(hook: WaterfallHookFn): void;
216
+ /**
217
+ * Removes a specific hook function from the waterfall chain
218
+ */
219
+ removeHook(hook: WaterfallHookFn): boolean;
220
+ }
221
+ type OnHookOptions = {
222
+ /**
223
+ * Per-call override for useHookClone.
224
+ * When true, hook objects are cloned before storing.
225
+ * When false, the original IHook reference is stored directly.
226
+ * When undefined, falls back to the instance-level useHookClone setting.
227
+ * @type {boolean}
184
228
  */
185
- throwHookErrors?: boolean;
229
+ useHookClone?: boolean;
230
+ /**
231
+ * Controls where the hook is inserted in the handlers array.
232
+ * - "Top": Insert at the beginning (index 0), before all existing handlers.
233
+ * - "Bottom": Append to the end, after all existing handlers. This is the default.
234
+ * - number: Insert at a specific index. Values are clamped to the array bounds.
235
+ */
236
+ position?: "Top" | "Bottom" | number;
237
+ };
238
+ type PrependHookOptions = Omit<OnHookOptions, "position">;
239
+ type HookifiedOptions = {
186
240
  /**
187
241
  * Whether an error should be thrown when a hook throws an error. Default is false and only emits an error event.
188
242
  */
@@ -205,26 +259,32 @@ type HookifiedOptions = {
205
259
  * @default true
206
260
  */
207
261
  allowDeprecated?: boolean;
262
+ /**
263
+ * Whether to clone hook objects before storing. Default is true.
264
+ * When false, the original IHook reference is stored directly.
265
+ * @type {boolean}
266
+ * @default true
267
+ */
268
+ useHookClone?: boolean;
208
269
  } & EventEmitterOptions;
209
270
 
210
271
  declare class Eventified implements IEventEmitter {
211
272
  private readonly _eventListeners;
212
273
  private _maxListeners;
213
- private _logger?;
274
+ private _eventLogger?;
214
275
  private _throwOnEmitError;
215
276
  private _throwOnEmptyListeners;
216
- private _errorEvent;
217
277
  constructor(options?: EventEmitterOptions);
218
278
  /**
219
- * Gets the logger
279
+ * Gets the event logger
220
280
  * @returns {Logger}
221
281
  */
222
- get logger(): Logger | undefined;
282
+ get eventLogger(): Logger | undefined;
223
283
  /**
224
- * Sets the logger
225
- * @param {Logger} logger
284
+ * Sets the event logger
285
+ * @param {Logger} eventLogger
226
286
  */
227
- set logger(logger: Logger | undefined);
287
+ set eventLogger(eventLogger: Logger | undefined);
228
288
  /**
229
289
  * Gets whether an error should be thrown when an emit throws an error. Default is false and only emits an error event.
230
290
  * @returns {boolean}
@@ -351,7 +411,57 @@ declare class Eventified implements IEventEmitter {
351
411
  * @param {string | symbol} eventName - The event name that determines the log level
352
412
  * @param {unknown} data - The data to log
353
413
  */
354
- private sendLog;
414
+ private sendToEventLogger;
415
+ }
416
+
417
+ /**
418
+ * Concrete implementation of the IHook interface.
419
+ * Provides a convenient class-based way to create hook entries.
420
+ */
421
+ declare class Hook implements IHook {
422
+ id?: string;
423
+ event: string;
424
+ handler: HookFn;
425
+ /**
426
+ * Creates a new Hook instance
427
+ * @param {string} event - The event name for the hook
428
+ * @param {HookFn} handler - The handler function for the hook
429
+ * @param {string} [id] - Optional unique identifier for the hook
430
+ */
431
+ constructor(event: string, handler: HookFn, id?: string);
432
+ }
433
+
434
+ /**
435
+ * A WaterfallHook chains multiple hook functions sequentially,
436
+ * where each hook receives a context with the previous result,
437
+ * initial arguments, and accumulated results. After all hooks
438
+ * have executed, the final handler receives the transformed result.
439
+ * Implements IHook for compatibility with Hookified.onHook().
440
+ */
441
+ declare class WaterfallHook implements IWaterfallHook {
442
+ id?: string;
443
+ event: string;
444
+ handler: HookFn;
445
+ hooks: WaterfallHookFn[];
446
+ private readonly _finalHandler;
447
+ /**
448
+ * Creates a new WaterfallHook instance
449
+ * @param {string} event - The event name for the hook
450
+ * @param {WaterfallHookFn} finalHandler - The final handler function that receives the transformed result
451
+ * @param {string} [id] - Optional unique identifier for the hook
452
+ */
453
+ constructor(event: string, finalHandler: WaterfallHookFn, id?: string);
454
+ /**
455
+ * Adds a hook function to the end of the waterfall chain
456
+ * @param {WaterfallHookFn} hook - The hook function to add
457
+ */
458
+ addHook(hook: WaterfallHookFn): void;
459
+ /**
460
+ * Removes a specific hook function from the waterfall chain
461
+ * @param {WaterfallHookFn} hook - The hook function to remove
462
+ * @returns {boolean} true if the hook was found and removed
463
+ */
464
+ removeHook(hook: WaterfallHookFn): boolean;
355
465
  }
356
466
 
357
467
  declare class Hookified extends Eventified {
@@ -360,24 +470,13 @@ declare class Hookified extends Eventified {
360
470
  private _enforceBeforeAfter;
361
471
  private _deprecatedHooks;
362
472
  private _allowDeprecated;
473
+ private _useHookClone;
363
474
  constructor(options?: HookifiedOptions);
364
475
  /**
365
476
  * Gets all hooks
366
- * @returns {Map<string, Hook[]>}
367
- */
368
- get hooks(): Map<string, Hook[]>;
369
- /**
370
- * Gets whether an error should be thrown when a hook throws an error. Default is false and only emits an error event.
371
- * @returns {boolean}
372
- * @deprecated - this will be deprecated in version 2. Please use throwOnHookError.
373
- */
374
- get throwHookErrors(): boolean;
375
- /**
376
- * Sets whether an error should be thrown when a hook throws an error. Default is false and only emits an error event.
377
- * @param {boolean} value
378
- * @deprecated - this will be deprecated in version 2. Please use throwOnHookError.
477
+ * @returns {Map<string, IHook[]>}
379
478
  */
380
- set throwHookErrors(value: boolean);
479
+ get hooks(): Map<string, IHook[]>;
381
480
  /**
382
481
  * Gets whether an error should be thrown when a hook throws an error. Default is false and only emits an error event.
383
482
  * @returns {boolean}
@@ -420,75 +519,72 @@ declare class Hookified extends Eventified {
420
519
  */
421
520
  set allowDeprecated(value: boolean);
422
521
  /**
423
- * Validates hook event name if enforceBeforeAfter is enabled
424
- * @param {string} event - The event name to validate
425
- * @throws {Error} If enforceBeforeAfter is true and event doesn't start with 'before' or 'after'
426
- */
427
- private validateHookName;
428
- /**
429
- * Checks if a hook is deprecated and emits a warning if it is
430
- * @param {string} event - The event name to check
431
- * @returns {boolean} - Returns true if the hook should proceed, false if it should be blocked
522
+ * Gets whether hook objects are cloned before storing. Default is true.
523
+ * @returns {boolean}
432
524
  */
433
- private checkDeprecatedHook;
525
+ get useHookClone(): boolean;
434
526
  /**
435
- * Adds a handler function for a specific event
436
- * @param {string} event
437
- * @param {Hook} handler - this can be async or sync
438
- * @returns {void}
527
+ * Sets whether hook objects are cloned before storing. Default is true.
528
+ * When false, the original IHook reference is stored directly.
529
+ * @param {boolean} value
439
530
  */
440
- onHook(event: string, handler: Hook): void;
531
+ set useHookClone(value: boolean);
441
532
  /**
442
- * Adds a handler function for a specific event
443
- * @param {HookEntry} hookEntry
444
- * @returns {void}
533
+ * Adds a handler function for a specific event.
534
+ * If you prefer the legacy `(event, handler)` signature, use {@link addHook} instead.
535
+ * To register multiple hooks at once, use {@link onHooks}.
536
+ * @param {IHook} hook - the hook containing event name and handler
537
+ * @param {OnHookOptions} [options] - optional per-call options (e.g., useHookClone override, position)
538
+ * @returns {IHook | undefined} the stored hook, or undefined if blocked by deprecation
445
539
  */
446
- onHookEntry(hookEntry: HookEntry): void;
540
+ onHook(hook: IHook, options?: OnHookOptions): IHook | undefined;
447
541
  /**
448
542
  * Alias for onHook. This is provided for compatibility with other libraries that use the `addHook` method.
449
- * @param {string} event
450
- * @param {Hook} handler - this can be async or sync
543
+ * @param {string} event - the event name
544
+ * @param {HookFn} handler - the handler function
451
545
  * @returns {void}
452
546
  */
453
- addHook(event: string, handler: Hook): void;
547
+ addHook(event: string, handler: HookFn): void;
454
548
  /**
455
- * Adds a handler function for a specific event
456
- * @param {Array<HookEntry>} hooks
549
+ * Adds handler functions for specific events
550
+ * @param {Array<IHook>} hooks
551
+ * @param {OnHookOptions} [options] - optional per-call options (e.g., useHookClone override, position)
457
552
  * @returns {void}
458
553
  */
459
- onHooks(hooks: HookEntry[]): void;
554
+ onHooks(hooks: IHook[], options?: OnHookOptions): void;
460
555
  /**
461
- * Adds a handler function for a specific event that runs before all other handlers
462
- * @param {string} event
463
- * @param {Hook} handler - this can be async or sync
464
- * @returns {void}
556
+ * Adds a handler function for a specific event that runs before all other handlers.
557
+ * Equivalent to calling `onHook(hook, { position: "Top" })`.
558
+ * @param {IHook} hook - the hook containing event name and handler
559
+ * @param {PrependHookOptions} [options] - optional per-call options (e.g., useHookClone override)
560
+ * @returns {IHook | undefined} the stored hook, or undefined if blocked by deprecation
465
561
  */
466
- prependHook(event: string, handler: Hook): void;
562
+ prependHook(hook: IHook, options?: PrependHookOptions): IHook | undefined;
467
563
  /**
468
- * Adds a handler that only executes once for a specific event before all other handlers
469
- * @param event
470
- * @param handler
564
+ * Adds a handler that only executes once for a specific event before all other handlers.
565
+ * Equivalent to calling `onHook` with a self-removing wrapper and `{ position: "Top" }`.
566
+ * @param {IHook} hook - the hook containing event name and handler
567
+ * @param {PrependHookOptions} [options] - optional per-call options (e.g., useHookClone override)
568
+ * @returns {IHook | undefined} the stored hook, or undefined if blocked by deprecation
471
569
  */
472
- prependOnceHook(event: string, handler: Hook): void;
570
+ prependOnceHook(hook: IHook, options?: PrependHookOptions): IHook | undefined;
473
571
  /**
474
572
  * Adds a handler that only executes once for a specific event
475
- * @param event
476
- * @param handler
573
+ * @param {IHook} hook - the hook containing event name and handler
477
574
  */
478
- onceHook(event: string, handler: Hook): void;
575
+ onceHook(hook: IHook): void;
479
576
  /**
480
577
  * Removes a handler function for a specific event
481
- * @param {string} event
482
- * @param {Hook} handler
483
- * @returns {void}
578
+ * @param {IHook} hook - the hook containing event name and handler to remove
579
+ * @returns {IHook | undefined} the removed hook, or undefined if not found
484
580
  */
485
- removeHook(event: string, handler: Hook): void;
581
+ removeHook(hook: IHook): IHook | undefined;
486
582
  /**
487
- * Removes all handlers for a specific event
488
- * @param {Array<HookEntry>} hooks
489
- * @returns {void}
583
+ * Removes multiple hook handlers
584
+ * @param {Array<IHook>} hooks
585
+ * @returns {IHook[]} the hooks that were successfully removed
490
586
  */
491
- removeHooks(hooks: HookEntry[]): void;
587
+ removeHooks(hooks: IHook[]): IHook[];
492
588
  /**
493
589
  * Calls all handlers for a specific event
494
590
  * @param {string} event
@@ -530,14 +626,44 @@ declare class Hookified extends Eventified {
530
626
  /**
531
627
  * Gets all hooks for a specific event
532
628
  * @param {string} event
533
- * @returns {Hook[]}
629
+ * @returns {IHook[]}
630
+ */
631
+ getHooks(event: string): IHook[] | undefined;
632
+ /**
633
+ * Gets a specific hook by id, searching across all events
634
+ * @param {string} id - the hook id
635
+ * @returns {IHook | undefined} the hook if found, or undefined
636
+ */
637
+ getHook(id: string): IHook | undefined;
638
+ /**
639
+ * Removes one or more hooks by id, searching across all events
640
+ * @param {string | string[]} id - the hook id or array of hook ids to remove
641
+ * @returns {IHook | IHook[] | undefined} the removed hook(s), or undefined/empty array if not found
534
642
  */
535
- getHooks(event: string): Hook[] | undefined;
643
+ removeHookById(id: string | string[]): IHook | IHook[] | undefined;
536
644
  /**
537
645
  * Removes all hooks
538
646
  * @returns {void}
539
647
  */
540
648
  clearHooks(): void;
649
+ /**
650
+ * Removes all hooks for a specific event and returns the removed hooks.
651
+ * @param {string} event - The event name to remove hooks for.
652
+ * @returns {IHook[]} the hooks that were removed
653
+ */
654
+ removeEventHooks(event: string): IHook[];
655
+ /**
656
+ * Validates hook event name if enforceBeforeAfter is enabled
657
+ * @param {string} event - The event name to validate
658
+ * @throws {Error} If enforceBeforeAfter is true and event doesn't start with 'before' or 'after'
659
+ */
660
+ private validateHookName;
661
+ /**
662
+ * Checks if a hook is deprecated and emits a warning if it is
663
+ * @param {string} event - The event name to check
664
+ * @returns {boolean} - Returns true if the hook should proceed, false if it should be blocked
665
+ */
666
+ private checkDeprecatedHook;
541
667
  }
542
668
 
543
- export { type EventEmitterOptions, type EventListener, Eventified, type Hook, type HookEntry, Hookified, type HookifiedOptions, type IEventEmitter, type Logger };
669
+ export { type EventEmitterOptions, type EventListener, Eventified, Hook, type HookFn, Hookified, type HookifiedOptions, type IEventEmitter, type IHook, type IWaterfallHook, type Logger, type OnHookOptions, type PrependHookOptions, WaterfallHook, type WaterfallHookContext, type WaterfallHookFn, type WaterfallHookResult };