hookified 1.15.0 → 2.0.0

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,33 @@ 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
277
  private _errorEvent;
217
278
  constructor(options?: EventEmitterOptions);
218
279
  /**
219
- * Gets the logger
280
+ * Gets the event logger
220
281
  * @returns {Logger}
221
282
  */
222
- get logger(): Logger | undefined;
283
+ get eventLogger(): Logger | undefined;
223
284
  /**
224
- * Sets the logger
225
- * @param {Logger} logger
285
+ * Sets the event logger
286
+ * @param {Logger} eventLogger
226
287
  */
227
- set logger(logger: Logger | undefined);
288
+ set eventLogger(eventLogger: Logger | undefined);
228
289
  /**
229
290
  * Gets whether an error should be thrown when an emit throws an error. Default is false and only emits an error event.
230
291
  * @returns {boolean}
@@ -351,7 +412,57 @@ declare class Eventified implements IEventEmitter {
351
412
  * @param {string | symbol} eventName - The event name that determines the log level
352
413
  * @param {unknown} data - The data to log
353
414
  */
354
- private sendLog;
415
+ private sendToEventLogger;
416
+ }
417
+
418
+ /**
419
+ * Concrete implementation of the IHook interface.
420
+ * Provides a convenient class-based way to create hook entries.
421
+ */
422
+ declare class Hook implements IHook {
423
+ id?: string;
424
+ event: string;
425
+ handler: HookFn;
426
+ /**
427
+ * Creates a new Hook instance
428
+ * @param {string} event - The event name for the hook
429
+ * @param {HookFn} handler - The handler function for the hook
430
+ * @param {string} [id] - Optional unique identifier for the hook
431
+ */
432
+ constructor(event: string, handler: HookFn, id?: string);
433
+ }
434
+
435
+ /**
436
+ * A WaterfallHook chains multiple hook functions sequentially,
437
+ * where each hook receives a context with the previous result,
438
+ * initial arguments, and accumulated results. After all hooks
439
+ * have executed, the final handler receives the transformed result.
440
+ * Implements IHook for compatibility with Hookified.onHook().
441
+ */
442
+ declare class WaterfallHook implements IWaterfallHook {
443
+ id?: string;
444
+ event: string;
445
+ handler: HookFn;
446
+ hooks: WaterfallHookFn[];
447
+ private readonly _finalHandler;
448
+ /**
449
+ * Creates a new WaterfallHook instance
450
+ * @param {string} event - The event name for the hook
451
+ * @param {WaterfallHookFn} finalHandler - The final handler function that receives the transformed result
452
+ * @param {string} [id] - Optional unique identifier for the hook
453
+ */
454
+ constructor(event: string, finalHandler: WaterfallHookFn, id?: string);
455
+ /**
456
+ * Adds a hook function to the end of the waterfall chain
457
+ * @param {WaterfallHookFn} hook - The hook function to add
458
+ */
459
+ addHook(hook: WaterfallHookFn): void;
460
+ /**
461
+ * Removes a specific hook function from the waterfall chain
462
+ * @param {WaterfallHookFn} hook - The hook function to remove
463
+ * @returns {boolean} true if the hook was found and removed
464
+ */
465
+ removeHook(hook: WaterfallHookFn): boolean;
355
466
  }
356
467
 
357
468
  declare class Hookified extends Eventified {
@@ -360,24 +471,13 @@ declare class Hookified extends Eventified {
360
471
  private _enforceBeforeAfter;
361
472
  private _deprecatedHooks;
362
473
  private _allowDeprecated;
474
+ private _useHookClone;
363
475
  constructor(options?: HookifiedOptions);
364
476
  /**
365
477
  * 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.
478
+ * @returns {Map<string, IHook[]>}
379
479
  */
380
- set throwHookErrors(value: boolean);
480
+ get hooks(): Map<string, IHook[]>;
381
481
  /**
382
482
  * Gets whether an error should be thrown when a hook throws an error. Default is false and only emits an error event.
383
483
  * @returns {boolean}
@@ -420,75 +520,72 @@ declare class Hookified extends Eventified {
420
520
  */
421
521
  set allowDeprecated(value: boolean);
422
522
  /**
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
523
+ * Gets whether hook objects are cloned before storing. Default is true.
524
+ * @returns {boolean}
432
525
  */
433
- private checkDeprecatedHook;
526
+ get useHookClone(): boolean;
434
527
  /**
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}
528
+ * Sets whether hook objects are cloned before storing. Default is true.
529
+ * When false, the original IHook reference is stored directly.
530
+ * @param {boolean} value
439
531
  */
440
- onHook(event: string, handler: Hook): void;
532
+ set useHookClone(value: boolean);
441
533
  /**
442
- * Adds a handler function for a specific event
443
- * @param {HookEntry} hookEntry
444
- * @returns {void}
534
+ * Adds a handler function for a specific event.
535
+ * If you prefer the legacy `(event, handler)` signature, use {@link addHook} instead.
536
+ * To register multiple hooks at once, use {@link onHooks}.
537
+ * @param {IHook} hook - the hook containing event name and handler
538
+ * @param {OnHookOptions} [options] - optional per-call options (e.g., useHookClone override, position)
539
+ * @returns {IHook | undefined} the stored hook, or undefined if blocked by deprecation
445
540
  */
446
- onHookEntry(hookEntry: HookEntry): void;
541
+ onHook(hook: IHook, options?: OnHookOptions): IHook | undefined;
447
542
  /**
448
543
  * 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
544
+ * @param {string} event - the event name
545
+ * @param {HookFn} handler - the handler function
451
546
  * @returns {void}
452
547
  */
453
- addHook(event: string, handler: Hook): void;
548
+ addHook(event: string, handler: HookFn): void;
454
549
  /**
455
- * Adds a handler function for a specific event
456
- * @param {Array<HookEntry>} hooks
550
+ * Adds handler functions for specific events
551
+ * @param {Array<IHook>} hooks
552
+ * @param {OnHookOptions} [options] - optional per-call options (e.g., useHookClone override, position)
457
553
  * @returns {void}
458
554
  */
459
- onHooks(hooks: HookEntry[]): void;
555
+ onHooks(hooks: IHook[], options?: OnHookOptions): void;
460
556
  /**
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}
557
+ * Adds a handler function for a specific event that runs before all other handlers.
558
+ * Equivalent to calling `onHook(hook, { position: "Top" })`.
559
+ * @param {IHook} hook - the hook containing event name and handler
560
+ * @param {PrependHookOptions} [options] - optional per-call options (e.g., useHookClone override)
561
+ * @returns {IHook | undefined} the stored hook, or undefined if blocked by deprecation
465
562
  */
466
- prependHook(event: string, handler: Hook): void;
563
+ prependHook(hook: IHook, options?: PrependHookOptions): IHook | undefined;
467
564
  /**
468
- * Adds a handler that only executes once for a specific event before all other handlers
469
- * @param event
470
- * @param handler
565
+ * Adds a handler that only executes once for a specific event before all other handlers.
566
+ * Equivalent to calling `onHook` with a self-removing wrapper and `{ position: "Top" }`.
567
+ * @param {IHook} hook - the hook containing event name and handler
568
+ * @param {PrependHookOptions} [options] - optional per-call options (e.g., useHookClone override)
569
+ * @returns {IHook | undefined} the stored hook, or undefined if blocked by deprecation
471
570
  */
472
- prependOnceHook(event: string, handler: Hook): void;
571
+ prependOnceHook(hook: IHook, options?: PrependHookOptions): IHook | undefined;
473
572
  /**
474
573
  * Adds a handler that only executes once for a specific event
475
- * @param event
476
- * @param handler
574
+ * @param {IHook} hook - the hook containing event name and handler
477
575
  */
478
- onceHook(event: string, handler: Hook): void;
576
+ onceHook(hook: IHook): void;
479
577
  /**
480
578
  * Removes a handler function for a specific event
481
- * @param {string} event
482
- * @param {Hook} handler
483
- * @returns {void}
579
+ * @param {IHook} hook - the hook containing event name and handler to remove
580
+ * @returns {IHook | undefined} the removed hook, or undefined if not found
484
581
  */
485
- removeHook(event: string, handler: Hook): void;
582
+ removeHook(hook: IHook): IHook | undefined;
486
583
  /**
487
- * Removes all handlers for a specific event
488
- * @param {Array<HookEntry>} hooks
489
- * @returns {void}
584
+ * Removes multiple hook handlers
585
+ * @param {Array<IHook>} hooks
586
+ * @returns {IHook[]} the hooks that were successfully removed
490
587
  */
491
- removeHooks(hooks: HookEntry[]): void;
588
+ removeHooks(hooks: IHook[]): IHook[];
492
589
  /**
493
590
  * Calls all handlers for a specific event
494
591
  * @param {string} event
@@ -530,14 +627,44 @@ declare class Hookified extends Eventified {
530
627
  /**
531
628
  * Gets all hooks for a specific event
532
629
  * @param {string} event
533
- * @returns {Hook[]}
630
+ * @returns {IHook[]}
631
+ */
632
+ getHooks(event: string): IHook[] | undefined;
633
+ /**
634
+ * Gets a specific hook by id, searching across all events
635
+ * @param {string} id - the hook id
636
+ * @returns {IHook | undefined} the hook if found, or undefined
637
+ */
638
+ getHook(id: string): IHook | undefined;
639
+ /**
640
+ * Removes one or more hooks by id, searching across all events
641
+ * @param {string | string[]} id - the hook id or array of hook ids to remove
642
+ * @returns {IHook | IHook[] | undefined} the removed hook(s), or undefined/empty array if not found
534
643
  */
535
- getHooks(event: string): Hook[] | undefined;
644
+ removeHookById(id: string | string[]): IHook | IHook[] | undefined;
536
645
  /**
537
646
  * Removes all hooks
538
647
  * @returns {void}
539
648
  */
540
649
  clearHooks(): void;
650
+ /**
651
+ * Removes all hooks for a specific event and returns the removed hooks.
652
+ * @param {string} event - The event name to remove hooks for.
653
+ * @returns {IHook[]} the hooks that were removed
654
+ */
655
+ removeEventHooks(event: string): IHook[];
656
+ /**
657
+ * Validates hook event name if enforceBeforeAfter is enabled
658
+ * @param {string} event - The event name to validate
659
+ * @throws {Error} If enforceBeforeAfter is true and event doesn't start with 'before' or 'after'
660
+ */
661
+ private validateHookName;
662
+ /**
663
+ * Checks if a hook is deprecated and emits a warning if it is
664
+ * @param {string} event - The event name to check
665
+ * @returns {boolean} - Returns true if the hook should proceed, false if it should be blocked
666
+ */
667
+ private checkDeprecatedHook;
541
668
  }
542
669
 
543
- export { type EventEmitterOptions, type EventListener, Eventified, type Hook, type HookEntry, Hookified, type HookifiedOptions, type IEventEmitter, type Logger };
670
+ 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 };