Manages a collection of before/after/error hooks and executes them around each transformation in the pipeline.
Usage
import { FilterCompiler, TransformationHookManager } from '@jk-com/adblock-compiler'; const hookManager = new TransformationHookManager(); // Fluent registration hookManager .onBeforeTransform((ctx) => console.log(`▶ ${ctx.name} — ${ctx.ruleCount} rules`)) .onAfterTransform((ctx) => console.log(`✔ ${ctx.name} — ${ctx.durationMs.toFixed(2)}ms`)) .onTransformError((ctx) => console.error(`✖ ${ctx.name}`, ctx.error)); const compiler = new FilterCompiler({ hookManager }); await compiler.compile(config);
Hook execution order
Hooks within each category are executed in registration order (FIFO).
Each hook is await-ed before the next, so you can safely perform
asynchronous work (e.g. writing to a database, emitting a metric) inside a
hook without worrying about race conditions.
Error isolation
If a beforeTransform or afterTransform hook throws, the exception
propagates up and will abort the pipeline. Wrap hook bodies in try-catch if
you want them to be non-fatal.
onError hooks are also awaited sequentially before the pipeline re-throws
the original transformation error — they are observers, not catch handlers.
Performance
When no hooks are registered hasHooks() returns false and the pipeline
skips all hook-invocation overhead entirely. For zero-hook scenarios use
NoOpHookManager (the default) which overrides the execute methods to
be empty no-ops, completely eliminating even the hasHooks() check cost.
TransformationHookManager(config?: TransformationHookConfig)
Creates a new TransformationHookManager.
Pass an initial TransformationHookConfig to bulk-register hooks in
one call, or start with an empty manager and use the fluent on* methods:
// Declarative (all hooks at construction time) const mgr = new TransformationHookManager(createLoggingHook(myLogger)); // Imperative (add hooks later) const mgr = new TransformationHookManager(); mgr.onAfterTransform(myTimingHook);
afterHooks: AfterTransformHook[]
beforeHooks: BeforeTransformHook[]
errorHooks: TransformErrorHook[]
clear(): void
Remove all registered hooks from this manager.
Useful in tests or when you want to reconfigure a manager without creating a new instance.
executeAfterHooks(context: TransformationHookContext & { inputCount: number; outputCount: number; durationMs: number; }): Promise<void>
Execute all registered afterTransform hooks in order.
Called by the pipeline immediately after a successful
transformation.execute() call. Each hook is awaited sequentially.
The context includes the wall-clock duration and rule counts for diffing.
executeBeforeHooks(context: TransformationHookContext): Promise<void>
Execute all registered beforeTransform hooks in order.
Called by the pipeline immediately before each transformation.execute()
call. Each hook is awaited sequentially.
executeErrorHooks(context: TransformationHookContext & { error: Error; }): Promise<void>
Execute all registered onError hooks in order.
Called by the pipeline inside the try-catch that wraps each
transformation.execute(). Each hook is awaited sequentially.
After all hooks have run the pipeline re-throws the original error.
hasHooks(): boolean
Returns true if at least one hook of any type has been registered.
The TransformationPipeline calls this as a fast-path guard before
each hook execution block. When no hooks are registered the pipeline
avoids constructing context objects and awaiting async calls entirely,
keeping the hot transform loop overhead at zero.
onAfterTransform(hook: AfterTransformHook): this
Register a hook to run after each transformation completes.
Multiple hooks can be registered; they fire in registration order.
onBeforeTransform(hook: BeforeTransformHook): this
Register a hook to run before each transformation.
Multiple hooks can be registered; they fire in registration order.
onTransformError(hook: TransformErrorHook): this
Register a hook to run when a transformation throws an error.
Error hooks are observers — they cannot suppress or replace the thrown error. After all error hooks complete, the pipeline re-throws the original error unchanged.